home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 1997 #3 / Amiga Plus CD - 1997 - No. 03.iso / pd / programmierung / vbcc / machines / amiga68k / machine.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-02-09  |  99.3 KB  |  2,403 lines

  1. /*  $VER: vbcc (machine.c amiga68k) V0.4    */
  2.  
  3. /*  Code generator for Motorola 680x0 CPUs. Supports 68000-68060+68881/2.   */
  4. /*  PhxAss and the GNU assembler is supported.                              */
  5.  
  6. #include "vbc.h"
  7.  
  8. static char FILE_[]=__FILE__;
  9.  
  10. /*  Public data that MUST be there.                             */
  11.  
  12. /*  Commandline-flags the code-generator accepts                */
  13. int g_flags[MAXGF]={VALFLAG,VALFLAG,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
  14. char *g_flags_name[MAXGF]={
  15.     "cpu","fpu","d2scratch","noa4","sc","sd","prof","const-in-data",
  16.     "use-framepointer","no-addressing-modes","no-delayed-popping",
  17.     "gas","branch-opt","no-fp-return","no-mreg-return","g"};
  18.  
  19. union ppi g_flags_val[MAXGF];
  20.  
  21. /*  Alignment-requirements for all types in bytes.              */
  22. zlong align[16];
  23.  
  24. /*  Alignment that is sufficient for every object.              */
  25. zlong maxalign=2;
  26.  
  27. /*  CHAR_BIT of the target machine.                             */
  28. zlong char_bit;
  29.  
  30. /*  Sizes of all elementary types in bytes.                     */
  31. zlong sizetab[16];
  32.  
  33. /*  Minimum and Maximum values each type can have.              */
  34. /*  Must be initialized in init_cg().                           */
  35. zlong t_min[32];
  36. zulong t_max[32];
  37.  
  38. /*  Names of all registers.                                     */
  39. char *regnames[MAXR+1]={"noreg","a0","a1","a2","a3","a4","a5","a6","a7",
  40.                                "d0","d1","d2","d3","d4","d5","d6","d7",
  41.                         "fp0","fp1","fp2","fp3","fp4","fp5","fp6","fp7"};
  42.  
  43. /*  The Size of each register in bytes.                         */
  44. zlong regsize[MAXR+1];
  45.  
  46. /*  regsa[reg]!=0 if a certain register is allocated and should */
  47. /*  not be used by the compiler pass.                           */
  48. int regsa[MAXR+1]={0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
  49.  
  50. /*  Specifies which registers may be scratched by functions.    */
  51. int regscratch[MAXR+1]={0,1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0};
  52.  
  53.  
  54. /****************************************/
  55. /*  Some private data and functions.    */
  56. /****************************************/
  57.  
  58. static long malign[16]={1,1,2,2,2,2,2,2,2,2,2,2,2,2,2};
  59. static long msizetab[16]={0,1,2,4,4,4,8,0,4,0,0,0,4,0};
  60.  
  61. static char reglist[200];
  62.  
  63. #define DATA 0
  64. #define BSS 1
  65. #define CODE 2
  66.  
  67. static int reglabel,freglabel,section=-1;
  68. static char *codename,*bssname,*dataname;
  69.  
  70. static void probj2(FILE *,struct obj *,int);
  71. static struct IC *do_refs(FILE *,struct IC *);
  72. static void pr(FILE *,struct IC *);
  73. static int get_reg(FILE *,int,struct IC *);
  74. static long pof2(zulong);
  75. static void function_top(FILE *,struct Var *,long);
  76. static void function_bottom(FILE *f,struct Var *,long);
  77.  
  78. static void saveregs(FILE *,struct IC *),restoreregsa(FILE *,struct IC *);
  79. static void restoreregsd(FILE *,struct IC *);
  80.  
  81. static void assign(FILE *,struct IC *,struct obj *,struct obj *,int,long,int);
  82. static int compare_objects(struct obj *o1,struct obj *o2);
  83.  
  84. static int is_const(struct Typ *t);
  85.  
  86. static char x_s[]={'0','b','w','3','l'};
  87. static char x_t[]={'?','b','w','l','l','s','d','v','l','a','s','u','e','f','?','?'};
  88.  
  89. static char *quick[2]={"","q"};
  90. static char *strshort[2]={"l","w"};
  91.  
  92. static char *ubranch[]={"eq","ne","cs","cc","ls","hi"};
  93.  
  94. static int pushedreg,stored_cc; /* pushedreg&2: aregsaved; 4: dreg; 8: freg */
  95.                                 /* 16: durch RESTOREREGS gepushed           */
  96. static int pushlabel,pushflag;
  97. static int geta4;
  98.  
  99. #define D16OFF 1024
  100.  
  101. static int newobj=0;   /*  um zu erkennen, ob neue section erlaubt ist */
  102.  
  103. static int gas,dbout;
  104.  
  105. static int isquickkonst(union atyps *,int),isquickkonst2(union atyps *,int),regavailable(int);
  106. static void move(FILE *,struct obj *,int,struct obj *,int,int);
  107. static void add(FILE *,struct obj *,int,struct obj *,int,int);
  108. static void sub(FILE *,struct obj *,int,struct obj *,int,int);
  109. static void mult(FILE *,struct obj *,int,struct obj *,int,int,int,struct IC *);
  110.  
  111. static long pof2(zulong x)
  112. /*  Yields log2(x)+1 oder 0. */
  113. {
  114.     zulong p;int ln=1;
  115.     p=ul2zul(1L);
  116.     while(zulleq(p,x)){
  117.         if(zuleqto(x,p)) return(ln);
  118.         ln++;p=zuladd(p,p);
  119.     }
  120.     return(0);
  121. }
  122.  
  123. #define isreg(x) ((p->x.flags&(REG|DREFOBJ))==REG)
  124.  
  125. #define PEA 1000
  126.  
  127. static int addressing(void);
  128. static long notpopped,dontpop,stackoffset,loff;
  129. static int offlabel,regoffset;
  130. /*  For keeping track of condition codes.   */
  131. static struct obj *cc_set,*cc_set_tst;
  132. static int cc_typ,cc_typ_tst;
  133.  
  134. static int pget_reg(FILE *f,int flag,struct IC *p)
  135. {
  136.     int i;
  137.     flag=1+flag*8;
  138.     for(i=flag;i<flag+8;i++){
  139.         if(regs[i]==1&&(!p||(i!=p->q1.reg&&i!=p->q2.reg&&i!=p->z.reg))){
  140.             if(p){
  141.                 if((p->q1.am&&(p->q1.am->dreg==i||p->q1.am->basereg==i))
  142.                  ||(p->q2.am&&(p->q2.am->dreg==i||p->q2.am->basereg==i))
  143.                  ||(p->z.am&&(p->z.am->dreg==i||p->z.am->basereg==i))){
  144.                     continue;
  145.                 }
  146.             }
  147.             regs[i]+=8;if(!pushlabel) {pushlabel=++label;pushflag=1;}
  148.             fprintf(f,"\tmove.l\t%s,l%d\n",regnames[i],pushlabel);
  149.             if(i<9) pushedreg|=2;
  150.             else if (i<17) pushedreg|=4;
  151.             else pushedreg|=8;
  152.             return(i);
  153.         }
  154.     }
  155.     ierror(0);
  156. }
  157. static int get_reg(FILE *f,int flag,struct IC *p)
  158. /*  Gets a register: flag=0=areg, 1=dreg, 2=fpreg           */
  159. {
  160.     int i;
  161.     flag=1+flag*8;
  162.     for(i=flag;i<flag+8;i++){
  163.         if(regs[i]==0){
  164.             if(p){
  165.                 if((p->q1.am&&(p->q1.am->dreg==i||p->q1.am->basereg==i))
  166.                  ||(p->q2.am&&(p->q2.am->dreg==i||p->q2.am->basereg==i))
  167.                  ||(p->z.am&&(p->z.am->dreg==i||p->z.am->basereg==i))){
  168. /*                    iwarning("%s used in get_reg(1)",regnames[i]);*/
  169.                     continue;
  170.                 }
  171.             }
  172.             regs[i]=2;pushedreg|=1;
  173.             if(!regused[i]&&!regscratch[i]){regused[i]=1; }
  174.             return(i);
  175.         }
  176.     }
  177.     for(i=flag;i<flag+8;i++){
  178.         if(regs[i]==1&&(!p||(i!=p->q1.reg&&i!=p->q2.reg&&i!=p->z.reg))){
  179.             if(p){
  180.                 if((p->q1.am&&(p->q1.am->dreg==i||p->q1.am->basereg==i))
  181.                  ||(p->q2.am&&(p->q2.am->dreg==i||p->q2.am->basereg==i))
  182.                  ||(p->z.am&&(p->z.am->dreg==i||p->z.am->basereg==i))){
  183. /*                    iwarning("%s used in get_reg(2)",regnames[i]);*/
  184.                     continue;
  185.                 }
  186.             }
  187.             regs[i]+=4;
  188.             if(i<17) {fprintf(f,"\tmove.l\t%s,-(a7)\n",regnames[i]);stackoffset-=4;}
  189.              else {fprintf(f,"\tfmove.x\t%s,-(a7)\n",regnames[i]);stackoffset-=12;}
  190. /*            if(p->code==COMPARE) ierror("corrupt code for compare generated - sorry");*/
  191.             if(i<9) pushedreg|=2;
  192.             else if (i<17) pushedreg|=4;
  193.             else pushedreg|=8;
  194.             return(i);
  195.         }
  196.     }
  197.     ierror(0);
  198. }
  199. static int isquickkonst(union atyps *p,int t)
  200. /*  Returns 1 if constant is between -128 and 127.   */
  201. {
  202.     zlong zl;zulong zul;
  203.     eval_const(p,t);
  204.     if(t&UNSIGNED){
  205.         zul=ul2zul(127UL);
  206.         return(zulleq(vulong,zul));
  207.     }else{
  208.         zl=l2zl(-129L);
  209.         if(zlleq(vlong,zl)) return(0);
  210.         zl=l2zl(127L);
  211.         return(zlleq(vlong,zl));
  212.     }
  213. }
  214. static int isquickkonst2(union atyps *p,int t)
  215. /*  Returns 1 if constant is between 1 and 8.   */
  216. {
  217.     zlong zl;zulong zul;
  218.     eval_const(p,t);
  219.     if(t&UNSIGNED){
  220.         if(zuleqto(ul2zul(0UL),vulong)) return(0);
  221.         zul=ul2zul(8UL);
  222.         return(zulleq(vulong,zul));
  223.     }else{
  224.         if(zleqto(l2zl(0L),vlong)) return(0);
  225.         zl=l2zl(-1L);
  226.         if(zlleq(vlong,zl)) return(0);
  227.         zl=l2zl(8L);
  228.         return(zlleq(vlong,zl));
  229.     }
  230. }
  231. static int regavailable(int art)
  232. /*  Returns true if matching register is available.     */
  233. {
  234.     int i;
  235.     art=1+art*8;
  236.     for(i=art+1;i<art+8;i++)
  237.         if(regs[i]==0) return(1);
  238.     return(0);
  239. }
  240. static int compare_objects(struct obj *o1,struct obj *o2)
  241. /*  Tests if two objects are equal.     */
  242. {
  243.     if(o1->flags==o2->flags&&o1->am==o2->am){
  244.         if(!(o1->flags&VAR)||(o1->v==o2->v&&zleqto(o1->val.vlong,o2->val.vlong))){
  245.             if(!(o1->flags®)||o1->reg==o2->reg){
  246.                 return(1);
  247.             }
  248.         }
  249.     }
  250.     return(0);
  251. }
  252. static struct IC *do_refs(FILE *f,struct IC *p)
  253. /*  Loads DREFOBJs into address registers, if necessary.    */
  254. /*  Small constants are loaded into data registers if this  */
  255. /*  improves code.                                          */
  256. {
  257.     int reg,c=p->code,t=p->typf,equal;
  258.     if((p->q1.flags&DREFOBJ)&&(!(p->q1.flags®)||p->q1.reg<1||p->q1.reg>8)){
  259.         equal=0;
  260.         if(compare_objects(&p->q1,&p->q2)) equal|=1;
  261.         if(compare_objects(&p->q1,&p->z)) equal|=2;
  262.         reg=get_reg(f,0,p);
  263.         p->q1.flags&=~DREFOBJ;
  264.         fprintf(f,"\tmove.l\t");probj2(f,&p->q1,t);
  265.         p->q1.flags=REG|DREFOBJ;
  266.         p->q1.reg=reg;
  267.         fprintf(f,",%s\n",regnames[p->q1.reg]);
  268.         if(equal&1) p->q2=p->q1;
  269.         if(equal&2) p->z=p->q1;
  270.     }
  271.     if((p->q2.flags&DREFOBJ)&&(!(p->q2.flags®)||p->q2.reg<1||p->q2.reg>8)){
  272.         if(compare_objects(&p->q2,&p->z)) equal=1; else equal=0;
  273.         reg=get_reg(f,0,p);
  274.         p->q2.flags&=~DREFOBJ;
  275.         fprintf(f,"\tmove.l\t");probj2(f,&p->q2,t);
  276.         p->q2.flags=REG|DREFOBJ;
  277.         p->q2.reg=reg;
  278.         fprintf(f,",%s\n",regnames[p->q2.reg]);
  279.         if(equal) p->z=p->q2;
  280.     }
  281.     if((p->z.flags&DREFOBJ)&&(!(p->z.flags®)||p->z.reg<1||p->z.reg>8)){
  282.         reg=get_reg(f,0,p);
  283.         p->z.flags&=~DREFOBJ;
  284.         fprintf(f,"\tmove.l\t");probj2(f,&p->z,t);
  285.         p->z.flags=REG|DREFOBJ;
  286.         p->z.reg=reg;
  287.         fprintf(f,",%s\n",regnames[p->z.reg]);
  288.     }
  289.     if(g_flags_val[0].l!=68040){
  290.     /*  Don't do it on 040 because it's slower. */
  291.         if(x_t[t&15]=='l'&&(t&15)!=FLOAT&&(c!=ASSIGN||!isreg(z))&&
  292.            c!=MULT&&c!=DIV&&c!=MOD&&c!=LSHIFT&&c!=RSHIFT&&c!=SETRETURN&&c!=PUSH&&c!=ADDI2P&&c!=SUBIFP&&
  293.            (!(p->z.flags®)||p->z.reg<9||p->z.reg>16)){
  294.             /*  Constants into registers.    */
  295.             if((p->q1.flags&KONST)&&isquickkonst(&p->q1.val,t)&&((c!=ADD&&c!=SUB&&c!=ADDI2P&&c!=SUBIFP)||!isquickkonst2(&p->q1.val,t))){
  296.                 eval_const(&p->q1.val,t);
  297.                 if((!zdeqto(d2zd(0.0),vdouble)||!zleqto(l2zl(0L),vlong)||!zuleqto(ul2zul(0UL),vulong))&®available(1)){
  298.                     reg=get_reg(f,1,p);
  299.                     move(f,&p->q1,0,0,reg,t);
  300.                     p->q1.flags=REG;p->q1.reg=reg;
  301.                     p->q1.val.vlong=l2zl(0L);
  302.                 }
  303.             }
  304.             if((p->q2.flags&KONST)&&isquickkonst(&p->q2.val,t)&&((c!=ADD&&c!=SUB&&c!=ADDI2P&&c!=SUBIFP)||!isquickkonst2(&p->q2.val,t))){
  305.                 eval_const(&p->q2.val,t);
  306.                 if((!zdeqto(d2zd(0.0),vdouble)||!zleqto(l2zl(0L),vlong)||!zuleqto(ul2zul(0UL),vulong))&®available(1)){
  307.                     reg=get_reg(f,1,p);
  308.                     move(f,&p->q2,0,0,reg,t);
  309.                     p->q2.flags=REG;p->q2.reg=reg;
  310.                     p->q2.val.vlong=l2zl(0L);
  311.                 }
  312.             }
  313.         }
  314.     }
  315.     return(p);
  316. }
  317. static void pr(FILE *f,struct IC *p)
  318. /*  Release registers and pop them from stack if necessary. */
  319. {
  320.     int i,size=0;
  321.     /*  To keep track of condition codes.   */
  322.     if((pushedreg&12)&&(p->code==TEST||p->code==COMPARE)){
  323.         char *fp;struct IC *branch;
  324.         if(g_flags_val[1].l>=68000&&((p->typf&15)==FLOAT||(p->typf&15)==DOUBLE)) fp="f"; else fp="";
  325.         branch=p;
  326.         while(branch->code<BEQ||branch->code>=BRA) branch=branch->next;
  327.         if((p->typf&UNSIGNED)||(p->typf&15)==POINTER){
  328.             fprintf(f,"\ts%s\t-2(a7)\n",ubranch[branch->code-BEQ]);
  329.         }else{
  330.             fprintf(f,"\t%ss%s\t-2(a7)\n",fp,ename[branch->code]+1);
  331.         }
  332.         stored_cc=1;
  333.     }
  334.     for(i=MAXR;i>0;i--){
  335.         if(regs[i]==2) regs[i]=0;
  336.         if(regs[i]&8){
  337.             regs[i]&=~8;
  338.             fprintf(f,"\tmove.l\tl%d,%s\n",pushlabel,regnames[i]);
  339.             if(i>=9) cc_set=0;
  340.         }
  341.         if(regs[i]&4){
  342.             regs[i]&=~4;
  343.             if(i<17) {fprintf(f,"\tmove.l\t(a7)+,%s\n",regnames[i]);stackoffset+=4;size+=4;}
  344.              else {fprintf(f,"\tfmove.x\t(a7)+,%s\n",regnames[i]);stackoffset+=12;size+=12;}
  345.             if(i>=9) cc_set=0;
  346.         }
  347.     }
  348.     if((pushedreg&12)&&(p->code==TEST||p->code==COMPARE))
  349.         fprintf(f,"\ttst.b\t-%d(a7)\n",size+2);
  350. }
  351. static void probj2(FILE *f,struct obj *p,int t)
  352. /*  Write object.   */
  353. {
  354.     if(p->am){
  355.     /*  Addressing modes.   */
  356.         if(g_flags[9]&USEDFLAG) {ierror(0);p->am=0;return;}
  357.         if(p->am->skal>=0){
  358.             long l=0;
  359.             if(p->flags&D16OFF) l=zl2l(p->val.vlong);
  360.             fprintf(f,"(%ld,%s",p->am->dist+l,regnames[p->am->basereg]);
  361.             if(p->am->dreg){
  362.                 fprintf(f,",%s",regnames[p->am->dreg&127]);
  363.                 if(p->am->dreg&128) fprintf(f,".w"); else fprintf(f,".l");
  364.                 if(p->am->skal) fprintf(f,"*%d",p->am->skal);
  365.             }
  366.             fprintf(f,")");
  367.             return;
  368.         }
  369.         if((p->flags&D16OFF)&&!zleqto(l2zl(0L),p->val.vlong)) ierror(0);
  370.         if(p->am->skal==-1){
  371.             fprintf(f,"(%s)+",regnames[p->am->basereg]);
  372.             return;
  373.         }
  374.         if(p->am->skal==-2){    /*  Noch nicht implementiert    */
  375.             fprintf(f,"-(%s)",regnames[p->am->basereg]);
  376.             return;
  377.         }
  378.     }
  379.     if(p->flags&DREFOBJ){
  380.         fprintf(f,"(");
  381.         if((p->flags&D16OFF)&&!zleqto(l2zl(0L),p->val.vlong))
  382.             {printval(f,&p->val,LONG,0);fprintf(f,",");}
  383.     }
  384.     if(p->flags&VARADR) fprintf(f,"#");
  385.     if(p->flags&VAR) {
  386.         if(p->v->storage_class==AUTO||p->v->storage_class==REGISTER){
  387.             if(p->flags®){
  388.                 fprintf(f,"%s",regnames[p->reg]);
  389.             }else{
  390.                 long os;
  391.                 os=zl2l(p->val.vlong);
  392.                 if(!(g_flags[8]&USEDFLAG)){
  393.                     if(!zlleq(l2zl(0L),p->v->offset)) os=os+loff-zl2l(p->v->offset);
  394.                      else              os=os+zl2l(p->v->offset);
  395.                     fprintf(f,"(%ld+l%d,a7)",os-stackoffset,offlabel);
  396.                 }else{
  397.                     if(!zlleq(l2zl(0L),p->v->offset)) os=os-zl2l(p->v->offset)+4;
  398.                      else              os=os-(zl2l(p->v->offset)+zl2l(szof(p->v->vtyp)));
  399.                     fprintf(f,"(%ld,a5)",os);
  400.                 }
  401.             }
  402.         }else{
  403.             if(!zleqto(l2zl(0L),p->val.vlong)){printval(f,&p->val,LONG,0);fprintf(f,"+");}
  404.             if(p->v->storage_class==STATIC&&(p->v->vtyp->flags&15)!=FUNKT){
  405.                 fprintf(f,"l%ld",zl2l(p->v->offset));
  406.             }else{
  407.                 fprintf(f,"_%s",p->v->identifier);
  408.             }
  409.             if((g_flags[5]&USEDFLAG)&&!(p->flags&VARADR)&&(p->v->vtyp->flags&15)!=FUNKT&&((g_flags[7]&USEDFLAG)||!is_const(p->v->vtyp)) )
  410.                 fprintf(f,"(a4)");
  411.         }
  412.     }
  413.     if((p->flags®)&&!(p->flags&VAR)) fprintf(f,"%s",regnames[p->reg]);
  414.     if(p->flags&KONST){
  415.         /*  This requires IEEE floats/doubles on the host compiler. */
  416.         if(t==FLOAT||t==DOUBLE){
  417.             unsigned char *ip=(unsigned char *)&p->val.vfloat;
  418.             char *s;
  419.             if(gas) s="0x"; else s="$";
  420.             fprintf(f,"#%s%02x%02x%02x%02x",s,ip[0],ip[1],ip[2],ip[3]);
  421.             if(t==DOUBLE){
  422.                 if(DEBUG&1) printf("doubleconst=%f\n",p->val.vdouble);
  423.                 fprintf(f,"%02x%02x%02x%02x",ip[4],ip[5],ip[6],ip[7]);
  424.             }
  425.         }else {fprintf(f,"#");printval(f,&p->val,t&31,0);}
  426.     }
  427.     if(p->flags&DREFOBJ) fprintf(f,")");
  428. }
  429. static char tsh[]={'w','l'};
  430. static int proflabel;
  431. static void function_top(FILE *f,struct Var *v,long offset)
  432. /*  Writes function header. */
  433. {
  434.     geta4=0;
  435.     if(gas){
  436.     }else{
  437.         if(g_flags[15]&USEDFLAG) fprintf(f,"\tsymdebug\n");
  438.         if(g_flags_val[0].l!=68000) fprintf(f,"\tmachine\t%ld\n",g_flags_val[0].l);
  439.         if(g_flags_val[1].l>68000) fprintf(f,"\tfpu\t1\n");
  440.         if(g_flags[4]&USEDFLAG) fprintf(f,"\tnear\tcode\n");
  441.         if(g_flags[5]&USEDFLAG) fprintf(f,"\tnear\ta4,-2\n");
  442.         fprintf(f,"\topt\t0\n\topt\tNQLPSM");
  443.         if(g_flags_val[0].l!=68040) fprintf(f,"R");
  444.         if((g_flags[12]&USEDFLAG)||(c_flags_val[0].l&2)) fprintf(f,"BT");
  445.         fprintf(f,"\n");
  446.     }
  447.     if(section!=CODE){fprintf(f,codename);section=CODE;}
  448.     if(g_flags[6]&USEDFLAG){
  449.         proflabel=++label;
  450.         if(gas){
  451.             fprintf(f,"l%d:\n\t.byte\t\"%s\",0\n",proflabel,v->identifier);
  452.         }else{
  453.             fprintf(f,"l%d\n\tdc.b\t\"%s\",0\n",proflabel,v->identifier);
  454.         }
  455.     }
  456.     if(v->storage_class==EXTERN){
  457.         if(gas){
  458.             fprintf(f,"\t.global\t_%s\n",v->identifier);
  459.         }else{
  460.             fprintf(f,"\tpublic\t_%s\n",v->identifier);
  461.         }
  462.     }
  463.     if(gas){
  464.         fprintf(f,"\t.align\t2\n_%s:\n",v->identifier);
  465.     }else{
  466.         fprintf(f,"\tcnop\t0,4\n_%s\n",v->identifier);
  467.     }
  468.     if(g_flags[6]&USEDFLAG){
  469.         if(gas){
  470.             fprintf(f,"\tpea\tl%d\n\t.global\t__startprof\n\tjbsr\t__startprof\n\taddq.w\t#4,a7\n",proflabel);
  471.         }else{
  472.             fprintf(f,"\tpea\tl%d\n\tpublic\t__startprof\n\tjsr\t__startprof\n\taddq.w\t#4,a7\n",proflabel);
  473.         }
  474.     }
  475.     offset=-((offset+4-1)/4)*4;
  476.     loff=-offset;offlabel=++label;
  477.     if(!(g_flags[8]&USEDFLAG)){
  478.         if(offset<0) fprintf(f,"\tsub%s.%s\t#%ld,a7\n",quick[offset>=-8],strshort[offset>=-32768],-offset);
  479.     }else{
  480.         if(offset>=-32768||g_flags_val[0].l>=68020){
  481.             fprintf(f,"\tlink.%c\ta5,#%ld\n",tsh[offset<-32768],offset);
  482.         }else{
  483.             fprintf(f,"\tlink.w\ta5,#-32768\n");offset+=32768;
  484.             fprintf(f,"\tsub.%c\t#%ld,a5\n",tsh[offset<-32768],offset);
  485.         }
  486.     }
  487.     if(g_flags_val[1].l>68000&&float_used){
  488.         if(gas){
  489.             fprintf(f,"\t.word\t0xf227,l%d\n",freglabel);
  490.         }else{
  491.             fprintf(f,"\tfmovem.x\tl%d,-(a7)\n",freglabel);
  492.         }
  493.     }
  494.     if(gas){
  495.         fprintf(f,"\tmovem.l\t#l%d,-(a7)\n",reglabel);
  496.     }else{
  497.         fprintf(f,"\tmovem.l\tl%d,-(a7)\n",reglabel);
  498.     }
  499. }
  500. static void function_bottom(FILE *f,struct Var *v,long offset)
  501. /*  Writes function footer. */
  502. {
  503.     int i,size=0;unsigned int pushval,popval;
  504.     *reglist=0;
  505.     pushval=popval=0;
  506.     for(i=1;i<=16;i++){
  507.         if((regused[i]&&!regscratch[i]&&!regsa[i])||(i==5&&geta4)){
  508.             if(*reglist) strcat(reglist,"/");
  509.             strcat(reglist,regnames[i]);
  510.             if(i<9){  pushval|=(256>>i);popval|=(128<<i);}
  511.               else {  pushval|=(0x8000>>(i-9));popval|=(1<<(i-9));}
  512.             size+=4;
  513.         }
  514.     }
  515.     if(gas){
  516.         if(popval) fprintf(f,"\t.equ\tl%d,%u\n\tmovem.l\t(a7)+,#%u\n",reglabel,pushval,popval);
  517.             else fprintf(f,"\t.equ\tl%d,0\n",reglabel);
  518.     }else{
  519.         if(*reglist) fprintf(f,"l%d\treg\t%s\n\tmovem.l\t(a7)+,l%d\n",reglabel,reglist,reglabel);
  520.             else fprintf(f,"l%d\treg\n",reglabel);
  521.     }
  522.     *reglist=0;pushval=0xe000;popval=0xd000;
  523.     for(i=17;i<=MAXR;i++){
  524.         if(regused[i]&&!regscratch[i]&&!regsa[i]){
  525.             if(*reglist) strcat(reglist,"/");
  526.             strcat(reglist,regnames[i]);
  527.             pushval|=(1<<(i-17));popval|=(0x80>>(i-17));
  528.             size+=12;
  529.         }
  530.     }
  531.     if(g_flags_val[1].l>68000&&float_used){
  532.         if(gas){
  533.             if(popval!=0xd000) fprintf(f,"\t.equ\tl%d,0x%x\n\t.word\t0xf21f,0x%x\n",freglabel,(int)pushval,(int)popval);
  534.                 else fprintf(f,"\t.equ\tl%d,0xe000\n",freglabel);
  535.         }else{
  536.             if(*reglist) fprintf(f,"l%d\tfreg\t%s\n\tfmovem.x\t(a7)+,l%d\n",freglabel,reglist,freglabel);
  537.                 else fprintf(f,"l%d\tfreg\n",freglabel);
  538.         }
  539.     }
  540.     if(!(g_flags[8]&USEDFLAG)){
  541.         if(loff) fprintf(f,"\tadd%s.%s\t#%ld,a7\n",quick[loff<=8],strshort[loff<32768],loff);
  542.         if(gas){
  543.             fprintf(f,"\t.equ\tl%d,%d\n",offlabel,size);
  544.         }else{
  545.             fprintf(f,"l%d\tEQU\t%d\n",offlabel,size);
  546.         }
  547.     }else fprintf(f,"\tunlk\ta5\n");
  548.     if(g_flags[6]&USEDFLAG){
  549.         if(gas){
  550.             fprintf(f,"\tpea\tl%d\n\t.global\t__endprof\n\tjbsr\t__endprof\n\taddq.w\t#4,a7\n",proflabel);
  551.         }else{
  552.             fprintf(f,"\tpea\tl%d\n\tpublic\t__endprof\n\tjsr\t__endprof\n\taddq.w\t#4,a7\n",proflabel);
  553.         }
  554.     }
  555.     fprintf(f,"\trts\n");
  556. }
  557. static void move(FILE *f,struct obj *q,int qreg,struct obj *z,int zreg,int t)
  558. /*  erzeugt eine move Anweisung...Da sollen mal Optimierungen rein  */
  559. {
  560.     if(!zreg&&(z->flags&(REG|DREFOBJ))==REG) zreg=z->reg;
  561.     if(!qreg&&(q->flags&(REG|DREFOBJ))==REG) qreg=q->reg;
  562.     if(zreg==qreg&&zreg) return;
  563.     if(q&&(q->flags&VARADR)&&zreg>=1&&zreg<=8){
  564.         fprintf(f,"\tlea\t");
  565.         q->flags&=~VARADR;probj2(f,q,t);q->flags|=VARADR;
  566.         fprintf(f,",%s\n",regnames[zreg]);
  567.         return;
  568.     }
  569.     if(zreg>=9&&zreg<=16&&q&&(q->flags&KONST)&&isquickkonst(&q->val,t)){
  570.         fprintf(f,"\tmoveq\t");
  571.     }else{
  572.         if(zreg>=17||qreg>=17){
  573.             if(qreg>=17&&zreg>=17) fprintf(f,"\tfmove.x\t");
  574.              else fprintf(f,"\tfmove.%c\t",x_t[t&15]);
  575.         }else{
  576.             fprintf(f,"\tmove.%c\t",x_s[msizetab[t&15]]);
  577.         }
  578.     }
  579.     if(qreg) fprintf(f,"%s",regnames[qreg]); else probj2(f,q,t);
  580.     fprintf(f,",");
  581.     if(zreg) fprintf(f,"%s",regnames[zreg]); else probj2(f,z,t);
  582.     fprintf(f,"\n");
  583. }
  584. static void add(FILE *f,struct obj *q,int qreg,struct obj *z,int zreg,int t)
  585. /*  erzeugt eine add Anweisung...Da sollen mal Optimierungen rein   */
  586. {
  587.     if(!qreg&&!q) ierror(0);
  588.     if(!zreg&&!z) ierror(0);
  589.     if(!zreg&&(z->flags&(REG|DREFOBJ))==REG) zreg=z->reg;
  590.     if(!qreg&&(q->flags&KONST)&&isquickkonst2(&q->val,t)){
  591.         fprintf(f,"\taddq.%c\t",x_t[t&15]);
  592.     }else{
  593.         /*  hier noch Abfrage, ob #c.w,ax   */
  594.         fprintf(f,"\tadd.%c\t",x_t[t&15]);
  595.     }
  596.     if(qreg) fprintf(f,"%s",regnames[qreg]); else probj2(f,q,t);
  597.     fprintf(f,",");
  598.     if(zreg) fprintf(f,"%s",regnames[zreg]); else probj2(f,z,t);
  599.     fprintf(f,"\n");
  600. }
  601. static void sub(FILE *f,struct obj *q,int qreg,struct obj *z,int zreg,int t)
  602. /*  erzeugt eine sub Anweisung...Da sollen mal Optimierungen rein   */
  603. {
  604.     if(!zreg&&(z->flags&(REG|DREFOBJ))==REG) zreg=z->reg;
  605.     if(q&&(q->flags&KONST)&&isquickkonst2(&q->val,t)){
  606.         fprintf(f,"\tsubq.%c\t",x_t[t&15]);
  607.     }else{
  608.         /*  hier noch Abfrage, ob #c.w,ax   */
  609.         fprintf(f,"\tsub.%c\t",x_t[t&15]);
  610.     }
  611.     if(qreg) fprintf(f,"%s",regnames[qreg]); else probj2(f,q,t);
  612.     fprintf(f,",");
  613.     if(zreg) fprintf(f,"%s",regnames[zreg]); else probj2(f,z,t);
  614.     fprintf(f,"\n");
  615. }
  616. static void mult(FILE *f,struct obj *q,int qreg,struct obj *z,int zreg, int t,int c,struct IC *p)
  617. /*  erzeugt eine mult Anweisung...Da sollen mal Optimierungen rein  */
  618. /*  erzeugt auch div/mod etc.                                       */
  619. {
  620.     int modreg;
  621.     if(!qreg&&(q->flags&(REG|DREFOBJ))==REG) qreg=q->reg;
  622.     if(!zreg&&(z->flags&(REG|DREFOBJ))==REG) zreg=z->reg;
  623.     if((c==MULT||c==DIV||c==MOD)&&g_flags_val[0].l<68020&&msizetab[t&15]==4){
  624.         if(c==MULT){
  625.         /*  ist das mit get_reg(.,.,0) ok? nochmal ueberdenken...   */
  626.         /*  ...die ganze Routine am besten...                       */
  627.         /*  ...es war nicht, deshalb ist es jetzt geaendert         */
  628.             int dx,dy,t1,t2;
  629.             if(zreg>=9&&zreg<=16){
  630.                 dx=zreg;
  631.             }else{
  632.                 dx=get_reg(f,1,p);
  633.                 move(f,z,0,0,dx,t);
  634.             }
  635.             if(qreg>=9&&qreg<=16&&qreg!=dx){
  636.                 dy=qreg;
  637.             }else{
  638.                 dy=get_reg(f,1,p);
  639.                 move(f,q,0,0,dy,t);
  640.             }
  641.             t1=get_reg(f,1,p);t2=get_reg(f,1,p);
  642.             if(t1==dx||t2==dx||t1==dy||t2==dy) ierror(0);
  643.             fprintf(f,"\tmove.l\t%s,%s\n",regnames[dx],regnames[t1]);
  644.             fprintf(f,"\tmove.l\t%s,%s\n",regnames[dy],regnames[t2]);
  645.             fprintf(f,"\tswap\t%s\n",regnames[t1]);
  646.             fprintf(f,"\tswap\t%s\n",regnames[t2]);
  647.             fprintf(f,"\tmulu.w\t%s,%s\n",regnames[dy],regnames[t1]);
  648.             fprintf(f,"\tmulu.w\t%s,%s\n",regnames[dx],regnames[t2]);
  649.             fprintf(f,"\tmulu.w\t%s,%s\n",regnames[dy],regnames[dx]);
  650.             fprintf(f,"\tadd.w\t%s,%s\n",regnames[t2],regnames[t1]);
  651.             fprintf(f,"\tswap\t%s\n",regnames[t1]);
  652.             fprintf(f,"\tclr.w\t%s\n",regnames[t1]);
  653.             fprintf(f,"\tadd.l\t%s,%s\n",regnames[t1],regnames[dx]);
  654.             if(zreg!=dx) move(f,0,t1,z,0,t);
  655.         }else ierror(0);
  656.         return;
  657.     }
  658.     if(c==MULT){
  659.         /*  das duerfte nur der Aesthetik dienen... */
  660.         if(t&UNSIGNED) fprintf(f,"\tmulu.%c\t",x_t[t&15]); else fprintf(f,"\tmuls.%c\t",x_t[t&15]);
  661.     }
  662.     if(c==DIV){
  663.         if(t&UNSIGNED) fprintf(f,"\tdivu.%c\t",x_t[t&15]); else fprintf(f,"\tdivs.%c\t",x_t[t&15]);
  664.     }
  665.     if(qreg) fprintf(f,"%s",regnames[qreg]); else probj2(f,q,t);
  666.     fprintf(f,",");
  667.     /*  eigentlich muss zreg!=0 sein...     */
  668.     if(zreg) fprintf(f,"%s",regnames[zreg]); else probj2(f,z,t);
  669.     fprintf(f,"\n");
  670. }
  671. static struct IC *am_freedreg[9],*am_shiftdreg[9];
  672. static struct IC *am_dist_ic[9],*am_dreg_ic[9],*am_use[9];
  673. /*  am_dist_ic und am_dreg_ic werden auch fuer (ax)+ benutzt    */
  674. static long am_dist[9],am_dreg[9],am_base[9],am_inc[9],am_skal[9],am_dbase[9];
  675. #define AMS sizeof(struct AddressingMode)
  676.  
  677. static void clear_am(int reg)
  678. /*  loescht Werte fuer erweiterte Adressierungsarten fuer Register reg  */
  679. {
  680.     if(reg<0||reg>16) ierror(0);
  681.     if(DEBUG&32) printf("clear_am(%s)\n",regnames[reg]);
  682.     if(reg<=8){
  683.         am_dist_ic[reg]=am_dreg_ic[reg]=am_use[reg]=0;
  684.         am_dist[reg]=am_dreg[reg]=am_base[reg]=am_inc[reg]=0;
  685.     }else{
  686.         reg-=8;
  687.         am_freedreg[reg]=am_shiftdreg[reg]=0;
  688.         am_skal[reg]=am_dbase[reg]=0;
  689.     }
  690. }
  691. static int addressing(void)
  692. /*  Untersucht ICs auf erweiterte Addresierungsarten    */
  693. {
  694.     struct IC *p;int count,localused=0;
  695.     if(DEBUG&32) printf("addressing() started\n");
  696.     for(count=1;count<=16;count++) clear_am(count);
  697.     for(count=0,p=first_ic;p;p=p->next){
  698.         int c=p->code,q1reg,q2reg,zreg;
  699.         if(p->q1.flags®) q1reg=p->q1.reg; else q1reg=0;
  700.         if(p->q2.flags®) q2reg=p->q2.reg; else q2reg=0;
  701.         if(p->z.flags®) zreg=p->z.reg; else zreg=0;
  702.         if(c==ADDI2P) c=ADD;
  703.         if(c==SUBIFP) c=SUB;
  704.         if(DEBUG&32) pric2(stdout,p);
  705.         if(!localused){
  706.             if((p->q1.flags&(VAR|REG))==VAR&&(p->q1.v->storage_class==AUTO||p->q1.v->storage_class==REGISTER)&&p->q1.v->offset>=0)
  707.                 localused=1;
  708.             if((p->q2.flags&(VAR|REG))==VAR&&(p->q2.v->storage_class==AUTO||p->q2.v->storage_class==REGISTER)&&p->q2.v->offset>=0)
  709.                 localused=1;
  710.             if((p->z.flags&(VAR|REG))==VAR&&(p->z.v->storage_class==AUTO||p->z.v->storage_class==REGISTER)&&p->z.v->offset>=0)
  711.                 localused=1;
  712.             if(DEBUG&32&&localused==1) printf("localused=1\n");
  713.         }
  714.         if(c==ASSIGN&&isreg(q1)&&isreg(z)&&q1reg>=1&&q1reg<=8&&zreg>=1&&zreg<=8){
  715.         /*  fuer (ax)+  */
  716.             int i;
  717.             clear_am(q1reg);
  718.             for(i=1;i<=8;i++)
  719.                 if(am_base[i]==zreg||am_base[i]==q1reg) clear_am(i);
  720.             clear_am(zreg);am_base[zreg]=q1reg;am_dreg_ic[zreg]=p;
  721.             if(DEBUG&32) printf("move %s,%s found\n",regnames[q1reg],regnames[zreg]);
  722.             continue;
  723.         }
  724.         if(c==MULT&&g_flags_val[0].l>=68020&&(p->q2.flags&KONST)&&isreg(z)&&zreg>=9&&zreg<=16){
  725.         /*  dx=a*const, fuer Skalierung    */
  726.             int dreg=zreg-8;
  727.             if(dreg<1||dreg>8) ierror(0);
  728.             if(DEBUG&32) printf("mult x,const->dreg found\n");
  729.             if(am_skal[dreg]) {clear_am(zreg);continue;}
  730.             eval_const(&p->q2.val,p->typf);
  731.             am_skal[dreg]=zl2l(vlong);
  732.             if(am_skal[dreg]!=2&&am_skal[dreg]!=4&&am_skal[dreg]!=8)
  733.                 {clear_am(zreg);continue;}
  734.             am_shiftdreg[dreg]=p;
  735.             if(isreg(q1)&&q1reg>=9&&q1reg<=16) am_dbase[dreg]=q1reg; else am_dbase[dreg]=zreg;
  736.             if(DEBUG&32) printf("is usable\n");
  737.             continue;
  738.         }
  739.         if((c==ADD||c==SUB)&&(p->q2.flags&KONST)&&zreg>=1&&zreg<=8&&isreg(z)){
  740.         /*  add ax,#const,ax->az Test auf d8/16 fehlt noch (nicht mehr) */
  741.             long l;
  742.             if(zreg<1||zreg>8) ierror(0);
  743.             eval_const(&p->q2.val,p->typf);
  744.             l=zl2l(vlong);
  745.             if(c==SUB) l=-l;
  746.             if(q1reg==zreg&&am_use[zreg]&&(l==1||l==2||l==4)){
  747.                 if(l==msizetab[am_use[zreg]->typf&15]){
  748.                     struct IC *op=am_use[zreg];
  749.                     struct obj *o=0;
  750.                     if(DEBUG&32){ printf("found postincrement:\n");pric2(stdout,op);pric2(stdout,p);}
  751.                     if((op->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&op->q1.reg==zreg){
  752.                         if(DEBUG&32) printf("q1\n");
  753.                         o=&op->q1;
  754.                     }
  755.                     if((op->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&op->q2.reg==zreg){
  756.                         if(DEBUG&32) printf("q2\n");
  757.                         if(o) continue; else o=&op->q2;
  758.                     }
  759.                     if((op->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&op->z.reg==zreg){
  760.                         if(DEBUG&32) printf("z\n");
  761.                         if(o) continue; else o=&op->z;
  762.                     }
  763.                     o->am=mymalloc(AMS);
  764.                     o->am->basereg=zreg;
  765.                     o->am->skal=-1;
  766.                     o->am->dist=0;
  767.                     o->am->dreg=0;
  768.                     p=p->prev;
  769.                     remove_IC(p->next);
  770.                     clear_am(zreg);continue;
  771.                 }
  772.             }
  773.             clear_am(q1reg);
  774.             if(am_dist[zreg]||am_inc[zreg]||am_use[zreg]) {clear_am(zreg);continue;} /* nur ein Offset */
  775.             if(isreg(q1)&&q1reg==zreg&&(l==1||l==2||l==4)){
  776.             /*  ax+=const, fuer (ax)+   */
  777.                 int i,f;
  778.                 for(f=0,i=1;i<=8;i++){
  779.                     if(am_base[i]==zreg&&!am_dreg[i]&&!am_dist[i]){
  780.                         if(f) ierror(0);
  781.                         am_inc[i]=l;am_dist_ic[i]=p;f=i;
  782.                         if(DEBUG&32) printf("inc %s found\n",regnames[i]);
  783.                     }
  784.                 }
  785.                 if(f) continue;
  786.             }
  787.             am_dist[zreg]=l;
  788.             if(DEBUG&32) printf("dist=%ld\n",am_dist[zreg]);
  789.             if(g_flags_val[0].l<68020){
  790.             /*  bei <68020 darf der Offset nur 16bit oder 8bit bei dreg sein */
  791.                 if((am_dreg[zreg]&&(am_dist[zreg]<-128||am_dist[zreg]>127))||am_dist[zreg]<-32768||am_dist[zreg]>32767)
  792.                     {clear_am(zreg);continue;}
  793.             }
  794.             am_dist_ic[zreg]=p;
  795.             if(am_base[zreg]){
  796.                 if(q1reg!=zreg||!isreg(q1)) {clear_am(zreg);continue;}
  797.             }else{
  798.                 if(q1reg>=1&&q1reg<=8&&isreg(q1)) am_base[zreg]=q1reg; else am_base[zreg]=zreg;
  799.                 if(DEBUG&32) printf("%s potential base for %s\n",regnames[am_base[zreg]],regnames[zreg]);
  800.             }
  801.             if(DEBUG&32) printf("add #const,%s found\n",regnames[zreg]);
  802.             continue;
  803.         }
  804.         if(c==ADD&&q2reg>=9&&q2reg<=16&&isreg(q2)&&zreg>=1&&zreg<=8&&isreg(z)&&(p->q1.flags&(REG|DREFOBJ))!=(REG|DREFOBJ)){
  805.         /*  add ax,dy->az   */
  806.             int i;
  807.             if(zreg<1||zreg>8) ierror(0);
  808.             for(i=1;i<=8;i++)
  809.                 if(am_dreg[i]==q2reg){ clear_am(q2reg);clear_am(i);}
  810.             clear_am(q1reg);
  811.             if(am_dreg[zreg]||am_inc[zreg]||am_use[zreg]) {clear_am(zreg);continue;} /* nur ein Regoffset */
  812.             if(g_flags_val[0].l<68020&&(am_dist[zreg]<-128||am_dist[zreg]>127))
  813.                 {clear_am(zreg);continue;} /* bei <68020 nur 8bit Offset */
  814.             am_dreg[zreg]=q2reg;
  815.             if((p->typf&15)==SHORT) am_dreg[zreg]|=128; /* dx.w statt dx.l */
  816.             am_dreg_ic[zreg]=p;
  817.             if(am_base[zreg]){
  818.                 if(q1reg!=zreg||!isreg(q1)) {clear_am(zreg);continue;}
  819.             }else{
  820.                 if(q1reg>=1&&q1reg<=8&&isreg(q1)) am_base[zreg]=q1reg; else am_base[zreg]=zreg;
  821.             }
  822.             if(DEBUG&32) printf("add %s,%s found\n",regnames[q2reg],regnames[zreg]);
  823.             continue;
  824.         }
  825.         if(c==FREEREG){
  826.         /*  wir koennen den Modus tatsaechlich benutzen */
  827.             struct AddressingMode *am;struct IC *p1,*p2;int dreg,i;
  828.             if(DEBUG&32) printf("freereg %s found\n",regnames[p->q1.reg]);
  829.             if(q1reg>=9&&q1reg<=16) {am_freedreg[q1reg-8]=p;if(DEBUG&32) printf("freedreg[%d]=%lx\n",q1reg-8,(long)p);}
  830.             if(q1reg>8) continue;
  831.             if(DEBUG&32) printf("use=%p,base=%p,dist=%p,dreg=%p\n",(void*)am_use[q1reg],(void*)am_base[q1reg],(void*)am_dist[q1reg],(void*)am_dreg[q1reg]);
  832.             for(i=1;i<=8;i++) if(am_base[i]==q1reg) clear_am(i);
  833.             if(!am_use[q1reg]||!am_base[q1reg]) continue;
  834.             if(!am_dist[q1reg]&&!am_dreg[q1reg]&&!am_inc[q1reg]) continue;
  835.             p1=am_dist_ic[q1reg];p2=am_dreg_ic[q1reg];
  836.             if(DEBUG&32){
  837.                 printf("could really use %s\n",regnames[q1reg]);
  838.                 if(p1) pric2(stdout,p1);
  839.                 if(p2) pric2(stdout,p2);
  840.             }
  841.             if(am_base[q1reg]==q1reg){
  842.                 if(p1) {p1->q2.flags=0;p1->code=ASSIGN;p1->q2.val.vlong=l2zl(4L);p1->typf=POINTER;}
  843.                 if(p2) {p2->q2.flags=0;p2->code=ASSIGN;p2->q2.val.vlong=l2zl(4L);p2->typf=POINTER;}
  844.             }else{
  845.                 if(p1) remove_IC(p1);
  846.                 if(p2) remove_IC(p2);
  847.             }
  848.             dreg=(am_dreg[q1reg]&127)-8;
  849.             am=mymalloc(AMS);
  850.             am->skal=0;
  851.             am->basereg=am_base[q1reg];
  852.             am->dist=am_dist[q1reg];
  853.             am->dreg=am_dreg[q1reg];
  854.             if(am_inc[q1reg]) am->skal=-1;
  855.             if(dreg>0){
  856.                 /*  bei (d,ax,dy) das freereg dy nach hinten verschieben    */
  857.                 if(dreg<1||dreg>8) ierror(0);
  858.                 if(p1=am_freedreg[dreg]){
  859.                     if(DEBUG&32){
  860.                         printf("freereg %s moved from %p to %p\n",regnames[dreg+8],(void*)p1,(void*)p);
  861.                         pric2(stdout,p1);
  862.                     }
  863.                     if(p1->code!=FREEREG){ierror(0);printf("freereg[%d]=%p\n",dreg,(void*)p1);continue;}
  864.                     if(!p1->next) {ierror(0);continue;}
  865.                     if(!p1->prev) {ierror(0);continue;}
  866.                     p1->prev->next=p1->next;
  867.                     p1->next->prev=p1->prev;
  868.                     p1->next=p->next;
  869.                     p1->prev=p;
  870.                     if(p->next) p->next->prev=p1;
  871.                     p->next=p1;
  872.                 }
  873.                 if(am_skal[dreg]){
  874.                 /*  Skalierung bearbeiten   */
  875.                     if(p1){
  876.                         am->skal=am_skal[dreg];
  877.                         am->dreg=am_dbase[dreg];
  878.                         p1=am_shiftdreg[dreg];
  879.                         if(DEBUG&32) pric2(stdout,p1);
  880.                         if(am_dbase[dreg]==dreg+8){
  881.                             p1->code=ASSIGN;p1->q2.flags=0;p1->q2.val.vlong=sizetab[p1->typf&15];
  882.                         }else remove_IC(p1);
  883.                     }
  884.                     clear_am(dreg+8);
  885.                 }
  886.             }
  887.             /*  das hier duerfte unnoetig sein, da die Adressierungsart in  */
  888.             /*  einem IC eigentlich hoechstens einmal vorkommen darf        */
  889.             if(q1reg<0||q1reg>8) ierror(0);
  890.             p1=am_use[q1reg];
  891.             if(DEBUG&32) pric2(stdout,p1);
  892.             if(p1->code==PUSH&&p1->q1.reg==q1reg&&((p1->q1.flags&(DREFOBJ|REG))==(REG))){
  893.                 p1->q1.am=mymalloc(AMS);
  894.                 memcpy(p1->q1.am,am,AMS);
  895.                 p->q1.val.vlong=l2zl(0L);
  896.                 p1->code=PEA;
  897.                 if(DEBUG&32) printf("q1 patched\n");
  898.             }
  899.             if(p1->q1.reg==q1reg&&((p1->q1.flags&(DREFOBJ|REG))==(DREFOBJ|REG))){
  900.                 p1->q1.am=mymalloc(AMS);
  901.                 memcpy(p1->q1.am,am,AMS);
  902.                 p1->q1.val.vlong=l2zl(0L);
  903.                 if(DEBUG&32) printf("q1 patched\n");
  904.             }
  905.             if(p1->q2.reg==q1reg&&((p1->q2.flags&(DREFOBJ|REG))==(DREFOBJ|REG))){
  906.                 p1->q2.am=mymalloc(AMS);
  907.                 memcpy(p1->q2.am,am,AMS);
  908.                 p1->q2.val.vlong=l2zl(0L);
  909.                 if(DEBUG&32) printf("q2 patched\n");
  910.             }
  911.             if(p1->z.reg==q1reg&&((p1->z.flags&(DREFOBJ|REG))==(DREFOBJ|REG))){
  912.                 p1->z.am=mymalloc(AMS);
  913.                 memcpy(p1->z.am,am,AMS);
  914.                 p1->z.val.vlong=l2zl(0L);
  915.                 if(DEBUG&32) printf("z patched\n");
  916.             }
  917.             free(am);count++;
  918.             clear_am(q1reg);
  919.             continue;
  920.         }
  921.         if(c>=LABEL&&c<=BRA){
  922.             int i;      /*  ueber basic blocks hinweg unsicher  */
  923.             for(i=1;i<=16;i++) clear_am(i);
  924.             continue;
  925.         }
  926.         /*  Wenn Libraryaufrufe noetig sind (floating point ohne FPU oder   */
  927.         /*  32bit mul/div/mod ohne 020+) keine Addressierungsarten nutzen   */
  928.         if(g_flags_val[1].l<68000&&(p->typf==FLOAT||p->typf==DOUBLE||c==CONVFLOAT||c==CONVDOUBLE)){
  929.             int i;
  930.             for(i=1;i<=16;i++) clear_am(i);
  931.             continue;
  932.         }
  933.         if(g_flags_val[0].l<68020&&(c==DIV||c==MOD)){
  934.             int i;
  935.             for(i=1;i<=16;i++) clear_am(i);
  936.             continue;
  937.         }
  938.         if(c==PUSH&&((p->q1.flags&(DREFOBJ|REG))==REG&&q1reg<=8&&(am_inc[q1reg]||am_dist[q1reg]||am_dreg[q1reg]))){
  939.             if(q1reg<1||q1reg>8) ierror(0);
  940.             if(am_inc[q1reg]&&am_inc[q1reg]!=msizetab[p->typf&15]) clear_am(q1reg); else am_use[q1reg]=p;
  941.             if(DEBUG&32) printf("use of %s found\n",regnames[q1reg]);
  942.             continue;
  943.         }
  944.         if(((p->q1.flags&(DREFOBJ|REG))==(DREFOBJ|REG)&&q1reg<=8)){
  945.             if(q1reg<1||q1reg>8) ierror(0);
  946.             if(am_use[q1reg]&&(am_use[q1reg]!=p||am_inc[q1reg])) clear_am(q1reg); else am_use[q1reg]=p;
  947.             if(am_inc[q1reg]&&am_inc[q1reg]!=sizetab[p->typf&15]) clear_am(q1reg);
  948.             if(DEBUG&32) printf("use of %s found\n",regnames[q1reg]);
  949.         }
  950.         if(((p->q2.flags&(DREFOBJ|REG))==(DREFOBJ|REG)&&q2reg<=8)){
  951.             if(q2reg<1||q2reg>8) ierror(0);
  952.             if(am_use[q2reg]&&(am_use[q2reg]!=p||am_inc[q2reg])) clear_am(q2reg); else am_use[q2reg]=p;
  953.             if(am_inc[q2reg]&&am_inc[q2reg]!=sizetab[p->typf&15]) clear_am(q2reg);
  954.             if(DEBUG&32) printf("use of %s found\n",regnames[q2reg]);
  955.         }
  956.         if(((p->z.flags&(DREFOBJ|REG))==(DREFOBJ|REG)&&zreg<=8)){
  957.             if(zreg<1||zreg>8) ierror(0);
  958.             if(am_use[zreg]&&(am_use[zreg]!=p||am_inc[zreg])) clear_am(zreg); else am_use[zreg]=p;
  959.             if(am_inc[zreg]&&am_inc[zreg]!=sizetab[p->typf&15]) clear_am(zreg);
  960.             if(DEBUG&32) printf("use of %s found\n",regnames[zreg]);
  961.         }
  962.         if(c==ALLOCREG){
  963.         /*  allocreg zaehlt als zerstoerung von reg */
  964.             p->z.flags=REG;
  965.             p->z.reg=zreg=q1reg;
  966.         }
  967.         if(q1reg>=1&&q1reg<=16&&isreg(q1)&&(q1reg>8||am_use[q1reg]!=p)) clear_am(q1reg);
  968.         if(q2reg>=1&&q2reg<=16&&isreg(q2)&&(q2reg>8||am_use[q2reg]!=p)) clear_am(q2reg);
  969.         if(zreg>=1&&zreg<=16&&isreg(z)) clear_am(zreg);
  970.         if(isreg(z)&&zreg<=16){
  971.         /*  schauen, ob eines der Register ueberschrieben wird  */
  972.         /*  wohl noch sehr langsam                              */
  973.             int i;
  974.             for(i=1;i<=8;i++)
  975.                 if(!am_use[i]&&(am_base[i]==zreg||(am_dreg[i]&127)==zreg)) clear_am(i);
  976.         }
  977.         if(c==ALLOCREG) p->z.flags=0;
  978.     }
  979.     if(DEBUG&1) printf("%d addressingmodes used, localused=%d\n",count,localused);
  980.     return(localused);
  981. }
  982. static int alignment(struct obj *o)
  983. /*  versucht rauszufinden, wie ein Objekt alignet ist   */
  984. {
  985.     /*  wenn es keine Variable ist, kann man nichts aussagen    */
  986.     long os;
  987.     if((o->flags&(DREFOBJ|VAR))!=VAR||o->am) return(0);
  988.     if(!o->v) ierror(0);
  989.     os=zl2l(o->val.vlong);
  990.     if(o->v->storage_class==AUTO||o->v->storage_class==REGISTER){
  991.         if(!(g_flags[8]&USEDFLAG)){
  992.             if(!zlleq(l2zl(0L),o->v->offset)) os=os+loff-zl2l(o->v->offset);
  993.              else              os=os+zl2l(o->v->offset);
  994.         }else{
  995.             if(!zlleq(l2zl(0L),o->v->offset)) os=os-zl2l(o->v->offset);
  996.              else              os=os-(zl2l(o->v->offset)+zl2l(szof(o->v->vtyp)));
  997.         }
  998.     }
  999.     return(os&3);
  1000. }
  1001. static void assign(FILE *f,struct IC *p,struct obj *q,struct obj *z,int c,long size,int t)
  1002. /*  Generiert Code fuer Zuweisungen und PUSH.   */
  1003. {
  1004.     /*  auch noch sehr fpu-spezifisch   */
  1005.     if((t&15)==FLOAT||(t&15)==DOUBLE){
  1006.         if(q&&(q->flags&KONST)){
  1007.             if(z&&(z->flags&(DREFOBJ|REG))==REG){
  1008.             /*  FP-Konstante->Register (muss immer reinpassen)  */
  1009.                 if(z->reg>=17) fprintf(f,"\tfmove"); else fprintf(f,"\tmove");
  1010.                 fprintf(f,".%c\t",x_t[t&15]);probj2(f,q,t);
  1011.                 fprintf(f,",%s\n",regnames[z->reg]);
  1012.             }else{
  1013.             /*  FP-Konstante->Speicher (evtl. auf zweimal)  */
  1014.                 int m;unsigned char *ip=(unsigned char *)&q->val.vfloat; /* nicht sehr schoen  */
  1015.                 char *s;
  1016.                 if(gas) s="0x"; else s="$";
  1017.                 if(c==PUSH&&t==DOUBLE){
  1018.                     fprintf(f,"\tmove.l\t#%s%02x%02x%02x%02x,-(a7)\n",s,ip[4],ip[5],ip[6],ip[7]);
  1019.                     stackoffset-=4;
  1020.                 }
  1021.                 fprintf(f,"\tmove.l\t#%s%02x%02x%02x%02x,",s,ip[0],ip[1],ip[2],ip[3]);
  1022.                 if(c==ASSIGN) probj2(f,z,t); else {fprintf(f,"-(a7)");stackoffset-=4;}
  1023.                 fprintf(f,"\n");
  1024.                 if(t!=DOUBLE||c==PUSH) return;
  1025.                 m=0;
  1026.                 if(z&&z->flags®){
  1027.                     m=1;z->flags|=D16OFF;
  1028.                     z->val.vlong=l2zl(0L);
  1029.                 }
  1030.                 vlong=l2zl(4L);
  1031.                 z->val.vlong=zladd(z->val.vlong,vlong);
  1032.                 fprintf(f,"\tmove.l\t#%s%02x%02x%02x%02x,",s,ip[4],ip[5],ip[6],ip[7]);
  1033.                 probj2(f,z,t);
  1034.                 fprintf(f,"\n");
  1035.                 if(m){
  1036.                     z->flags&=~D16OFF;vlong=l2zl(4L);
  1037.                     z->val.vlong=zlsub(z->val.vlong,vlong);
  1038.                 }
  1039.             }
  1040.             return;
  1041.         }
  1042.         if((q&&(q->flags®)&&q->reg>=17)||(z&&(z->flags®)&&z->reg>=17)){
  1043.             if(c==ASSIGN&&q->reg==z->reg) return;
  1044.             if(c==ASSIGN){ move(f,q,0,z,0,t);return;}
  1045.             fprintf(f,"\tfmove.%c\t",x_t[t&15]);
  1046.             probj2(f,q,t);
  1047.             fprintf(f,",");
  1048.             if(c==PUSH) {fprintf(f,"-(a7)");stackoffset-=size;} else probj2(f,z,t);
  1049.             fprintf(f,"\n");return;
  1050.         }
  1051.     }
  1052.     if(size<=4&&(t&15)!=ARRAY&&((t&15)!=CHAR||size==1)){
  1053.         if((t&15)==STRUCT||(t&15)==UNION){
  1054.             if(size==2) t=SHORT; else t=LONG;
  1055.         }
  1056.         if(c==ASSIGN){move(f,q,0,z,0,t);return;}
  1057.         /*  Sonderfall pea  */
  1058.         if((q->flags&VARADR)&&c==PUSH){
  1059.             fprintf(f,"\tpea\t");
  1060.             q->flags&=~VARADR; probj2(f,q,t); q->flags|=VARADR;
  1061.             fprintf(f,"\n"); stackoffset-=4;return;
  1062.         }
  1063.         fprintf(f,"\tmove.%c\t",x_s[size]);
  1064.         probj2(f,q,t);
  1065.         fprintf(f,",");
  1066.         if(c==PUSH) {fprintf(f,"-(a7)");stackoffset-=size;} else probj2(f,z,t);
  1067.         fprintf(f,"\n");return;
  1068.     }else{
  1069.         int a1,a2,qreg,zreg,dreg,s=size,loops,scratch=0;char *cpstr;
  1070.         struct IC *m;
  1071.         for(m=p->next;m&&m->code==FREEREG;m=m->next){
  1072.             if(m->q1.reg==q->reg) scratch|=1;
  1073.             if(m->q1.reg==z->reg) scratch|=2;
  1074.         }
  1075.         if(c==PUSH) cpstr="\tmove.%c\t-(%s),-(%s)\n"; else cpstr="\tmove.%c\t(%s)+,(%s)+\n";
  1076.         if((c==PUSH||(scratch&1))&&(q->flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&q->reg>=1&&q->reg<=8&&!q->am){
  1077.             qreg=q->reg;
  1078.             if(c==PUSH)
  1079.                 fprintf(f,"\tadd%s.%s\t#%ld,%s\n",quick[s<=8],strshort[s<=32767],(long)s,regnames[q->reg]);
  1080.         }else{
  1081.             if(c!=ASSIGN&&!regavailable(0)) qreg=pget_reg(f,0,p);
  1082.                 else qreg=get_reg(f,0,p);
  1083.             if(c==PUSH){q->flags|=D16OFF; q->val.vlong=zladd(q->val.vlong,l2zl((long)s));}
  1084.             fprintf(f,"\tlea\t");probj2(f,q,POINTER);
  1085.             if(c==PUSH) q->val.vlong=zlsub(q->val.vlong,l2zl((long)s));
  1086.             fprintf(f,",%s\n",regnames[qreg]);
  1087.         }
  1088.         if(c==PUSH){
  1089.             zreg=8;
  1090. /*            fprintf(f,"\tadd%s.%s\t#%ld,%s\n",quick[s<=8],strshort[s<=32767],(long)s,regnames[qreg]);*/
  1091.         }else{
  1092.             if((scratch&2)&&(z->flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&z->reg>=1&&z->reg<=8&&!z->am){
  1093.                 zreg=z->reg;
  1094.             }else{
  1095.                 zreg=get_reg(f,0,p);
  1096.                 fprintf(f,"\tlea\t");probj2(f,z,POINTER);
  1097.                 fprintf(f,",%s\n",regnames[zreg]);
  1098.             }
  1099.         }
  1100.         a1=alignment(q);
  1101.         if(c!=PUSH)  a2=alignment(z); else a2=0;
  1102.         /*  wenn Typ==CHAR, dann ist das ein inline_memcpy und wir nehmen   */
  1103.         /*  das unguenstigste Alignment an                                  */
  1104.         if((t&15)==CHAR){ a1=1;a2=2;}
  1105.  
  1106.         if((a1&1)&&(a2&1)){fprintf(f,cpstr,'b',regnames[qreg],regnames[zreg]);s--;a1&=~1;a2&=~1;}
  1107.         if((a1&2)&&(a2&2)){fprintf(f,cpstr,'w',regnames[qreg],regnames[zreg]);s-=2;a1&=~2;a2&=~2;}
  1108.         if(!(a1&1)&&!(a2&1)) loops=s/16-1; else loops=s/4-1;
  1109.         if(loops>0){
  1110.             if(c!=ASSIGN&&!regavailable(1)) dreg=pget_reg(f,0,p);
  1111.                 else dreg=get_reg(f,1,p);
  1112.             fprintf(f,"\tmove%s.l\t#%d,%s\nl%d:\n",quick[loops>=-128&&loops<=127],loops,regnames[dreg],++label);
  1113.         }
  1114.         if(loops>=0){
  1115.             int t;
  1116.             if(!(a1&1)&&!(a2&1)) t='l'; else t='b';
  1117.             fprintf(f,cpstr,t,regnames[qreg],regnames[zreg]);
  1118.             fprintf(f,cpstr,t,regnames[qreg],regnames[zreg]);
  1119.             fprintf(f,cpstr,t,regnames[qreg],regnames[zreg]);
  1120.             fprintf(f,cpstr,t,regnames[qreg],regnames[zreg]);
  1121.         }
  1122.         if(loops>0){
  1123.             if(loops<=32767&&loops>=-32768){
  1124.                 fprintf(f,"\tdbra\t%s,l%d\n",regnames[dreg],label);
  1125.             }else{
  1126.                 fprintf(f,"\tsubq.l\t#1,%s\n\tbge\tl%d\n",regnames[dreg],label);
  1127.             }
  1128.         }
  1129.         if(!(a1&1)&&!(a2&1)){
  1130.             if(s&8){
  1131.                 fprintf(f,cpstr,'l',regnames[qreg],regnames[zreg]);
  1132.                 fprintf(f,cpstr,'l',regnames[qreg],regnames[zreg]);
  1133.             }
  1134.             if(s&4) fprintf(f,cpstr,'l',regnames[qreg],regnames[zreg]);
  1135.             if(s&2) fprintf(f,cpstr,'w',regnames[qreg],regnames[zreg]);
  1136.             if(s&1) fprintf(f,cpstr,'b',regnames[qreg],regnames[zreg]);
  1137.         }else{
  1138.             s&=3;
  1139.             while(s){fprintf(f,cpstr,'b',regnames[qreg],regnames[zreg]);s--;}
  1140.         }
  1141.         if(c==PUSH) stackoffset-=size;
  1142.     }
  1143.     return;
  1144. }
  1145. static int store_saveregs;
  1146. static void saveregs(FILE *f,struct IC *p)
  1147. {
  1148.     int dontsave;
  1149.     store_saveregs=0;
  1150.     if((p->z.flags&(REG|DREFOBJ))==REG) dontsave=p->z.reg; else dontsave=0;
  1151.     if(dontsave!= 9&®s[ 9]) {fprintf(f,"\tmove.l\td0,-(a7)\n");stackoffset-=4;store_saveregs|=1;}
  1152.     if(dontsave!=10&®s[10]) {fprintf(f,"\tmove.l\td1,-(a7)\n");stackoffset-=4;store_saveregs|=2;}
  1153.     if(dontsave!= 1&®s[ 1]) {fprintf(f,"\tmove.l\ta0,-(a7)\n");stackoffset-=4;store_saveregs|=4;}
  1154.     if(dontsave!= 2&®s[ 2]) {fprintf(f,"\tmove.l\ta1,-(a7)\n");stackoffset-=4;store_saveregs|=8;}
  1155. }
  1156. static void restoreregsa(FILE *f,struct IC *p)
  1157. {
  1158.     if(store_saveregs&8) {fprintf(f,"\tmove.l\t(a7)+,a1\n");stackoffset+=4;}
  1159.     if(store_saveregs&4) {fprintf(f,"\tmove.l\t(a7)+,a0\n");stackoffset+=4;}
  1160. }
  1161. static void restoreregsd(FILE *f,struct IC *p)
  1162. {
  1163.     int dontsave;
  1164.     if((p->z.flags&(REG|DREFOBJ))==REG) dontsave=p->z.reg; else dontsave=0;
  1165.     if(dontsave!=10&&(store_saveregs&2)) {fprintf(f,"\tmovem.l\t(a7)+,d1\n");stackoffset+=4;}
  1166.     if(dontsave!=9 &&(store_saveregs&1)) {fprintf(f,"\tmovem.l\t(a7)+,d0\n");stackoffset+=4;}
  1167. }
  1168. static int is_const(struct Typ *t)
  1169. /*  tested, ob ein Typ konstant (und damit evtl. in der Code-Section) ist   */
  1170. {
  1171.     if(!(t->flags&(CONST|STRINGCONST))){
  1172.         do{
  1173.             if(t->flags&(CONST|STRINGCONST)) return(1);
  1174.             if((t->flags&15)!=ARRAY) return(0);
  1175.             t=t->next;
  1176.         }while(1);
  1177.     }else return(1);
  1178. }
  1179.  
  1180.  
  1181. /****************************************/
  1182. /*  End of private fata and functions.  */
  1183. /****************************************/
  1184.  
  1185.  
  1186.  
  1187. int init_cg(void)
  1188. /*  Does necessary initializations for the code-generator. Gets called  */
  1189. /*  once at the beginning and should return 0 in case of problems.      */
  1190. {
  1191.     int i;
  1192.     /*  Initialize some values which cannot be statically initialized   */
  1193.     /*  because they are stored in the target's arithmetic.             */
  1194.     maxalign=l2zl(4L);
  1195.     char_bit=l2zl(8L);
  1196.     for(i=0;i<16;i++){
  1197.         sizetab[i]=l2zl(msizetab[i]);
  1198.         align[i]=l2zl(malign[i]);
  1199.     }
  1200.     for(i= 1;i<=16;i++) regsize[i]=l2zl( 4L);
  1201.     for(i=17;i<=24;i++) regsize[i]=l2zl(12L);
  1202.  
  1203.     /*  default CPU is 68000    */
  1204.     if(!(g_flags[0]&USEDFLAG)) g_flags_val[0].l=68000;
  1205.     /*  no FPU by default       */
  1206.     if(!(g_flags[1]&USEDFLAG)) g_flags_val[1].l=0;
  1207.     if(g_flags_val[1].l<68000) {x_t[FLOAT]='l';}
  1208.     if(g_flags[2]&USEDFLAG) regscratch[11]=1;
  1209.     if(g_flags[3]&USEDFLAG) regsa[5]=1;
  1210.     if(g_flags[15]&USEDFLAG) dbout=1;
  1211.     if(g_flags[11]&USEDFLAG){
  1212.         gas=1;
  1213.         codename="\t.text\n";
  1214.         bssname="";
  1215.         dataname="\t.data\n";
  1216.         if(g_flags[5]&USEDFLAG) regsa[5]=1;
  1217.     }else{
  1218.         codename="\tsection\t\"CODE\",code\n";
  1219.         if(g_flags[5]&USEDFLAG){
  1220.             /*  preparing small data    */
  1221.             regsa[5]=1;
  1222.             bssname= "\tsection\t\"__MERGED\",bss\n";
  1223.             dataname="\tsection\t\"__MERGED\",data\n";
  1224.         }else{
  1225.             bssname= "\tsection\t\"BSS\",bss\n";
  1226.             dataname="\tsection\t\"DATA\",data\n";
  1227.         }
  1228.     }
  1229.     /*  a5 can be used if no framepointer is used.  */
  1230.     if(!(g_flags[8]&USEDFLAG)) regsa[6]=0;
  1231.     if(DEBUG&1) printf("CPU=%ld FPU=%ld\n",g_flags_val[0].l,g_flags_val[1].l);
  1232.  
  1233.     /*  Initialize the min/max-settings. Note that the types of the     */
  1234.     /*  host system may be different from the target system and you may */
  1235.     /*  only use the smallest maximum values ANSI guarantees if you     */
  1236.     /*  want to be portable.                                            */
  1237.     /*  That's the reason for the subtraction in t_min[INT]. Long could */
  1238.     /*  be unable to represent -2147483648 on the host system.          */
  1239.     t_min[UNSIGNED|CHAR]=t_min[UNSIGNED|SHORT]=t_min[UNSIGNED|INT]=t_min[UNSIGNED|LONG]=l2zl(0L);
  1240.     t_min[CHAR]=l2zl(-128L);
  1241.     t_min[SHORT]=l2zl(-32768L);
  1242.     t_min[INT]=zlsub(l2zl(-2147483647L),l2zl(1L));
  1243.     t_min[LONG]=t_min[INT];
  1244.     t_max[CHAR]=ul2zul(127L);
  1245.     t_max[SHORT]=ul2zul(32767UL);
  1246.     t_max[INT]=ul2zul(2147483647UL);
  1247.     t_max[LONG]=t_max[INT];
  1248.     t_max[UNSIGNED|CHAR]=ul2zul(255UL);
  1249.     t_max[UNSIGNED|SHORT]=ul2zul(65535UL);
  1250.     t_max[UNSIGNED|INT]=ul2zul(4294967295UL);
  1251.     t_max[UNSIGNED|LONG]=t_max[UNSIGNED|INT];
  1252.  
  1253.     return(1);
  1254. }
  1255.  
  1256. int freturn(struct Typ *t)
  1257. /*  Returns the register in which variables of type t are returned. */
  1258. /*  If the value cannot be returned in a register returns 0.        */
  1259. {
  1260.     long l;int tu=t->flags&15;
  1261.     if(tu==FLOAT){
  1262.         if(g_flags_val[1].l>=68000&&!(g_flags[13]&USEDFLAG))
  1263.             return(17);
  1264.         else
  1265.             return(9);
  1266.     }
  1267.     if(tu==DOUBLE){
  1268.         if(g_flags_val[1].l>=68000&&!(g_flags[13]&USEDFLAG)){
  1269.             return(17);
  1270.         }else{
  1271.             if(g_flags[14]&USEDFLAG) return(0);
  1272.             return(9);
  1273.         }
  1274.     }
  1275.     if(tu==STRUCT||tu==UNION){
  1276.         if(!(g_flags[14]&USEDFLAG)){
  1277.             l=zl2l(szof(t));
  1278.             if(l==4||l==8||l==12||l==16) return(9);
  1279.         }
  1280.         return(0);
  1281.     }
  1282.     if(zlleq(szof(t),l2zl(4L))) return(9); else return(0);
  1283. }
  1284.  
  1285. int regok(int r,int t,int mode)
  1286. /*  Returns 0 if register r cannot store variables of   */
  1287. /*  type t. If t==POINTER and mode!=0 then it returns   */
  1288. /*  non-zero only if the register can store a pointer   */
  1289. /*  and dereference a pointer to mode.                  */
  1290. {
  1291.     if(r==0) return(0);
  1292.     t&=15;
  1293.     if(t==FLOAT||t==DOUBLE){
  1294.         if(g_flags_val[1].l>=68000){
  1295.             if(r>=17&&r<=24) return(1); else return(0);
  1296.         }else{
  1297.             if(t==FLOAT&&r>=9&&r<=16) return(1); else return(0);
  1298.         }
  1299.     }
  1300.     if(t==POINTER&&mode==0&&r>=9&&r<=16) return(1);
  1301.     if(t==POINTER&&r>=1&&r<=8) return(1);
  1302.     if(t>=CHAR&&t<=LONG&&r>=9&&r<=16) return(1);
  1303.     return(0);
  1304. }
  1305.  
  1306. int dangerous_IC(struct IC *p)
  1307. /*  Returns zero if the IC p can be safely executed     */
  1308. /*  without danger of exceptions or similar things.     */
  1309. /*  vbcc may generate code in which non-dangerous ICs   */
  1310. /*  are sometimes executed although control-flow may    */
  1311. /*  never reach them (mainly when moving computations   */
  1312. /*  out of loops).                                      */
  1313. /*  Typical ICs that generate exceptions on some        */
  1314. /*  machines are:                                       */
  1315. /*      - accesses via pointers                         */
  1316. /*      - division/modulo                               */
  1317. /*      - overflow on signed integer/floats             */
  1318. {
  1319.     int c=p->code;
  1320.     if((p->q1.flags&DREFOBJ)||(p->q2.flags&DREFOBJ)||(p->z.flags&DREFOBJ))
  1321.         return(0);
  1322.     if((c==DIV||c==MOD)&&!(p->q2.flags&KONST)) return(1);
  1323.     return(0);
  1324. }
  1325.  
  1326. int must_convert(np p,int t)
  1327. /*  Returns zero if code for converting np to type t    */
  1328. /*  can be omitted.                                     */
  1329. {
  1330.     int o=p->ntyp->flags,op=o&15,tp=t&15;
  1331.     /*  All pointers have the same representation.  */
  1332.     if(tp==POINTER&&op==POINTER) return(0);
  1333.     /*  Pointer and int/long as well   */
  1334. /*    if(tp==POINTER&&(op==INT||op==LONG)) return(0);
  1335.     if(op==POINTER&&(tp==INT||tp==LONG)) return(0);*/
  1336.     /*  Signed und Unsigned integers with the same size, too.  */
  1337.     if((t&UNSIGNED)&&(o&UNSIGNED)&&zleqto(sizetab[tp],sizetab[op])) return(0);
  1338.     /*  int==long   */
  1339.     if((tp==INT&&op==LONG)||(tp==LONG&&op==INT)) return(0);
  1340.  
  1341.     if((tp==FLOAT||tp==DOUBLE)&&(op==FLOAT||op==DOUBLE)&&(p->o.flags®)&&p->o.reg>=17&&p->o.reg<=24)
  1342.         return(0);
  1343.  
  1344.     return(1);
  1345. }
  1346.  
  1347. void gen_ds(FILE *f,zlong size,struct Typ *t)
  1348. /*  This function has to create <size> bytes of storage */
  1349. /*  initialized with zero.                              */
  1350. {
  1351.     if(gas){
  1352.         if(newobj) fprintf(f,"%ld\n",zl2l(size));
  1353.             else   fprintf(f,"\t.space\t%ld\n",zl2l(size));
  1354.         newobj=0;
  1355.     }else{
  1356.         if(section!=BSS&&newobj){fprintf(f,bssname);section=BSS;}
  1357.         fprintf(f,"\tds.b\t%ld\n",zl2l(size));newobj=0;
  1358.     }
  1359. }
  1360.  
  1361. void gen_align(FILE *f,zlong align)
  1362. /*  This function has to make sure the next data is     */
  1363. /*  aligned to multiples of <align> bytes.              */
  1364. {
  1365.     if(align>1){
  1366.         if(gas){
  1367.             fprintf(f,"\t.align\t2\n");
  1368.         }else{
  1369.             fprintf(f,"\tcnop\t0,4\n");
  1370.         }
  1371.     }
  1372. }
  1373. void gen_var_head(FILE *f,struct Var *v)
  1374. /*  This function has to create the head of a variable  */
  1375. /*  definition, i.e. the label and information for      */
  1376. /*  linkage etc.                                        */
  1377. {
  1378.     int constflag;
  1379.     if(v->clist) constflag=is_const(v->vtyp);
  1380.     if(v->storage_class==STATIC){
  1381.         if((v->vtyp->flags&15)==FUNKT) return;
  1382.         if(v->clist&&(!constflag||(g_flags[7]&USEDFLAG))&§ion!=DATA){fprintf(f,dataname);section=DATA;}
  1383.         if(v->clist&&constflag&&!(g_flags[7]&USEDFLAG)&§ion!=CODE){fprintf(f,codename);section=CODE;}
  1384.         if(!v->clist&§ion!=BSS){fprintf(f,bssname);section=BSS;}
  1385.         if(gas){
  1386.             if(section!=BSS) fprintf(f,"\t.align\t2\nl%ld:\n",zl2l(v->offset));
  1387.                 else fprintf(f,"\t.lcomm\tl%ld,",zl2l(v->offset));
  1388.         }else{
  1389.             fprintf(f,"\tcnop\t0,4\nl%ld\n",zl2l(v->offset));
  1390.         }
  1391.         newobj=1;
  1392.     }
  1393.     if(v->storage_class==EXTERN){
  1394.         if(gas){
  1395.             fprintf(f,"\t.global\t_%s\n",v->identifier);
  1396.         }else{
  1397.             fprintf(f,"\tpublic\t_%s\n",v->identifier);
  1398.         }
  1399.         if(v->flags&(DEFINED|TENTATIVE)){
  1400.             if(v->clist&&(!constflag||(g_flags[7]&USEDFLAG))&§ion!=DATA){fprintf(f,dataname);section=DATA;}
  1401.             if(v->clist&&constflag&&!(g_flags[7]&USEDFLAG)&§ion!=CODE){fprintf(f,codename);section=CODE;}
  1402.             if(!v->clist&§ion!=BSS){fprintf(f,bssname);section=BSS;}
  1403.             if(gas){
  1404.                 if(section!=BSS) fprintf(f,"\t.align\t2\n_%s:\n",v->identifier);
  1405.                     else fprintf(f,"\t.comm\t_%s,",v->identifier);
  1406.             }else{
  1407.                 fprintf(f,"\tcnop\t0,4\n_%s\n",v->identifier);
  1408.             }
  1409.             newobj=1;
  1410.         }
  1411.     }
  1412. }
  1413. void gen_dc(FILE *f,int t,struct const_list *p)
  1414. /*  This function has to create static storage          */
  1415. /*  initialized with const-list p.                      */
  1416. {
  1417.     char s;
  1418.     if(!p){ierror(0);return;}
  1419. /*    if(section!=DATA){fprintf(f,dataname);section=DATA;}*/
  1420.     if((t&15)==FLOAT||(t&15)==DOUBLE) s='l'; else s=x_t[t&15];
  1421.     if(gas){
  1422.         char *str;
  1423.         if(s=='b') str="\t.byte\t";
  1424.         else if(s=='w') str="\t.short\t";
  1425.         else if(s=='l') str="\t.long\t";
  1426.         else ierror(0);
  1427.         fprintf(f,"%s",str);
  1428.     }else{
  1429.         fprintf(f,"\tdc.%c\t",s);
  1430.     }
  1431.     if(!p->tree){
  1432.         if((t&15)==FLOAT||(t&15)==DOUBLE){
  1433.         /*  auch wieder nicht sehr schoen und IEEE noetig   */
  1434.             unsigned char *ip;char *s;
  1435.             ip=(unsigned char *)&p->val.vdouble;
  1436.             if(gas) s="0x"; else s="$";
  1437.             fprintf(f,"%s%02x%02x%02x%02x",s,ip[0],ip[1],ip[2],ip[3]);
  1438.             if((t&15)==DOUBLE){
  1439.                 fprintf(f,",%s%02x%02x%02x%02x",s,ip[4],ip[5],ip[6],ip[7]);
  1440.             }
  1441.         }else{
  1442.             printval(f,&p->val,t&31,0);
  1443.         }
  1444.     }else{
  1445.         int m,m2;
  1446.         p->tree->o.am=0;
  1447.         m=p->tree->o.flags;
  1448.         p->tree->o.flags&=~VARADR;
  1449.         m2=g_flags[5];
  1450.         g_flags[5]&=~USEDFLAG;
  1451.         probj2(f,&p->tree->o,t&31);
  1452.         p->tree->o.flags=m;
  1453.         g_flags[5]=m2;
  1454.     }
  1455.     fprintf(f,"\n");newobj=0;
  1456. }
  1457.  
  1458. /*  The main code-generation routine.                   */
  1459. /*  f is the stream the code should be written to.      */
  1460. /*  p is a pointer to a doubly linked list of ICs       */
  1461. /*  containing the function body to generate code for.  */
  1462. /*  v is a pointer to the function.                     */
  1463. /*  offset is the size of the stackframe the function   */
  1464. /*  needs for local variables.                          */
  1465.  
  1466. void gen_code(FILE *f,struct IC *p,struct Var *v,zlong offset)
  1467. {
  1468.     int c,t,comptyp;char fp[2]="\0\0";
  1469.     int act_line=0;char *act_file=0;
  1470.     if(DEBUG&1) printf("gen_code()\n");
  1471.     for(c=1;c<=MAXR;c++) regs[c]=regsa[c];
  1472.     if(!(g_flags[9]&USEDFLAG)){
  1473.     /*  Adressierungsarten benutzen */
  1474.         if(!addressing()) offset=l2zl(0L);
  1475.     }
  1476.     if(dbout){
  1477.         if(!gas){
  1478.             act_line=fline;
  1479.             fprintf(f,"\tdsource\t\"%s\"\n",errfname);
  1480.             fprintf(f,"\tdebug\t%d\n",act_line);
  1481.         }
  1482.     }
  1483.     reglabel=++label;freglabel=++label;
  1484.     function_top(f,v,zl2l(offset));
  1485.     if(p!=first_ic) ierror(0);
  1486.     cc_set=cc_set_tst=0;
  1487.     stackoffset=notpopped=dontpop=0;
  1488.     for(;p;pr(f,p),p=p->next){
  1489.         if(dbout){
  1490.         /*  Hier soll spaeter mal das Sourcefile angegeben werden.  */
  1491.             if(p->file&&p->file!=act_file) ierror(0);
  1492.             if(p->line&&p->line!=act_line){
  1493.                 act_line=p->line;
  1494.                 if(!gas) fprintf(f,"\tdebug\t%d\n",act_line);
  1495.             }
  1496.         }
  1497.         c=p->code;t=p->typf;
  1498.         if(c==NOP) continue;
  1499.         cc_set_tst=cc_set;
  1500.         cc_typ_tst=cc_typ;
  1501.         if(cc_set_tst&&(DEBUG&512)){fprintf(f,"; cc_set_tst=");probj2(f,cc_set_tst,t);fprintf(f,"\n");}
  1502.         if(cc_set&&(DEBUG&512)){fprintf(f,"; cc_set=");probj2(f,cc_set,t);fprintf(f,"\n");}
  1503.         pushedreg&=16;if(c==RESTOREREGS) pushedreg=0;
  1504.         if(DEBUG&256){fprintf(f,"; "); pric2(f,p);}
  1505.         if(DEBUG&512) fprintf(f,"; stackoffset=%ld, notpopped=%ld, pushedreg=%d, dontpop=%ld\n",stackoffset,notpopped,pushedreg,dontpop);
  1506.         /*  muessen wir Argumente poppen?   */
  1507.         if(notpopped&&!dontpop){
  1508.             int flag=0;
  1509.             if(c==LABEL||c==COMPARE||c==TEST||c==BRA){
  1510.                 fprintf(f,"\tadd%s.%s\t#%ld,a7\n",quick[notpopped<=8],strshort[notpopped<32768],notpopped);
  1511.                 stackoffset+=notpopped;notpopped=0;/*cc_set_tst=cc_set=0;*/
  1512.             }
  1513.         }
  1514.         /*  na, ob das hier ok ist..?   */
  1515.         if(c==SUBPFP) c=SUB;
  1516.         if(c==PMULT) c=MULT;
  1517.         if(c==ALLOCREG) {regs[p->q1.reg]=1;continue;}
  1518.         if(c==FREEREG) {regs[p->q1.reg]=0;continue;}
  1519.         if(c==LABEL){
  1520.             if(dbout) act_line=0;
  1521.             if(gas){
  1522.                 fprintf(f,"l%d:\n",t);
  1523.             }else{
  1524.                 fprintf(f,"l%d\n",t);
  1525.             }
  1526.             cc_set=0;continue;
  1527.         }
  1528.         if(c==BRA){fprintf(f,"\t%sbra\tl%d\n",(gas?"j":""),t);continue;}
  1529.         if(c>=BEQ&&c<BRA){
  1530.             if(gas){
  1531.                 if(stored_cc){fprintf(f,"\tjne\tl%d\n",t);stored_cc=0;continue;}
  1532.                 if((comptyp&UNSIGNED)||(comptyp&15)==POINTER){
  1533.                     fprintf(f,"\tj%s\tl%d\n",ubranch[c-BEQ],t);
  1534.                 }else{
  1535.                     fprintf(f,"\t%sj%s\tl%d\n",fp,ename[c]+1,t);
  1536.                 }
  1537.             }else{
  1538.                 if(stored_cc){fprintf(f,"\tbne\tl%d\n",t);stored_cc=0;continue;}
  1539.                 if((comptyp&UNSIGNED)||(comptyp&15)==POINTER){
  1540.                     fprintf(f,"\tb%s\tl%d\n",ubranch[c-BEQ],t);
  1541.                 }else{
  1542.                     fprintf(f,"\t%s%s\tl%d\n",fp,ename[c],t);
  1543.                 }
  1544.             }
  1545.             continue;
  1546.         }
  1547.         if(p->q1.am){
  1548.             if(!regs[p->q1.am->basereg]){pric2(stdout,p);printf("%s\n",regnames[p->q1.am->basereg]); ierror(0);}
  1549.             if(p->q1.am->dreg&&!regs[p->q1.am->dreg&127]) {printf("Register %s:\n",regnames[p->q1.am->dreg&127]);ierror(0);}
  1550.         }
  1551.         if(p->q2.am){
  1552.             if(!regs[p->q2.am->basereg]) ierror(0);
  1553.             if(p->q2.am->dreg&&!regs[p->q2.am->dreg&127]) {printf("Register %s:\n",regnames[p->q2.am->dreg&127]);ierror(0);}
  1554.         }
  1555.         if(p->z.am){
  1556.             if(!regs[p->z.am->basereg]) ierror(0);
  1557.             if(p->z.am->dreg&&!regs[p->z.am->dreg&127]) {printf("Register %s:\n",regnames[p->z.am->dreg&127]);ierror(0);}
  1558.         }
  1559.         if((p->q1.flags®)&&!regs[p->q1.reg]){printf("Register %s:\n",regnames[p->q1.reg]);ierror(0);}
  1560.         if((p->q2.flags®)&&!regs[p->q2.reg]){printf("Register %s:\n",regnames[p->q2.reg]);ierror(0);}
  1561.         if((p->z.flags®)&&!regs[p->z.reg]){printf("Register %s:\n",regnames[p->z.reg]);ierror(0);}
  1562.         if((p->q2.flags®)&&(p->z.flags®)&&p->q2.reg==p->z.reg){pric2(stdout,p);ierror(0);}
  1563.         if((p->q2.flags&VAR)&&(p->z.flags&VAR)&&p->q2.v==p->z.v){pric2(stdout,p);ierror(0);}
  1564.         /*  COMPARE #0 durch TEST ersetzen (erlaubt, da tst alle Flags setzt)   */
  1565.         if(c==COMPARE&&(p->q2.flags&KONST)){
  1566.             eval_const(&p->q2.val,t);
  1567.             if(zleqto(l2zl(0L),vlong)&&zuleqto(ul2zul(0UL),vulong)&&zdeqto(d2zd(0.0),vdouble)){
  1568.                 c=p->code=TEST;p->q2.flags=0;
  1569.             }
  1570.         }
  1571.         if(c==COMPARE&&(p->q1.flags&KONST)){
  1572.             eval_const(&p->q1.val,t);
  1573.             if(zleqto(l2zl(0L),vlong)&&zuleqto(ul2zul(0UL),vulong)&&zdeqto(d2zd(0.0),vdouble)){
  1574.                 struct IC *bp=p->next;int bc;
  1575.                 c=p->code=TEST;p->q1=p->q2;p->q2.flags=0;p->q2.am=0;
  1576.                 /*  Nachfolgenden Branch umdrehen   */
  1577.                 while(bp&&bp->code==FREEREG) bp=bp->next;
  1578.                 bc=bp->code;
  1579.                 if(!bp||bc<BEQ||bc>BGT) ierror(0);
  1580.                 if(bc==BLT) bp->code=BGT;
  1581.                 if(bc==BGT) bp->code=BLT;
  1582.                 if(bc==BLE) bp->code=BGE;
  1583.                 if(bc==BGE) bp->code=BLE;
  1584.             }
  1585.         }
  1586.         /*  gesetzte ConditionCodes merken  */
  1587.         if(p->z.flags&&(!isreg(z)||p->z.reg>=9)&&c!=CONVFLOAT&&c!=CONVDOUBLE&&(((t&15)!=FLOAT&&(t&15)!=DOUBLE)||g_flags_val[1].l>68000)){
  1588.              cc_set=&p->z;cc_typ=p->typf;
  1589.         }else{
  1590.             cc_set=0;
  1591.         }
  1592.         if(c==PEA){
  1593.             fprintf(f,"\tpea\t");probj2(f,&p->q1,t);fprintf(f,"\n");
  1594.             stackoffset-=zl2l(p->q2.val.vlong);
  1595.             dontpop+=zl2l(p->q2.val.vlong);
  1596.             continue;
  1597.         }
  1598.         if(c==MOVEFROMREG){
  1599.             if(p->q1.reg<17) fprintf(f,"\tmove.l\t%s,",regnames[p->q1.reg]);
  1600.                 else         fprintf(f,"\tfmove.x\t%s,",regnames[p->q1.reg]);
  1601.             probj2(f,&p->z,t);fprintf(f,"\n");
  1602.             continue;
  1603.         }
  1604.         if(c==MOVETOREG){
  1605.             if(p->z.reg<17) fprintf(f,"\tmove.l\t");
  1606.                 else        fprintf(f,"\tfmove.x\t");
  1607.             probj2(f,&p->q1,t);fprintf(f,",%s\n",regnames[p->z.reg]);
  1608.             continue;
  1609.         }
  1610.         if(g_flags[9]&USEDFLAG)
  1611.             if(p->q1.am||p->q2.am||p->z.am){
  1612.                 ierror(0);
  1613.                 p->q1.am=p->q2.am=p->z.am=0;
  1614.             }
  1615.         p=do_refs(f,p);
  1616.         if(g_flags[9]&USEDFLAG)
  1617.             if(p->q1.am||p->q2.am||p->z.am){
  1618.                 ierror(0);
  1619.                 p->q1.am=p->q2.am=p->z.am=0;
  1620.             }
  1621.         if(c>=CONVCHAR&&c<=CONVULONG){
  1622.             int to;
  1623.             if(c==CONVCHAR) to=CHAR;
  1624.             if(c==CONVUCHAR) to=UNSIGNED|CHAR;
  1625.             if(c==CONVSHORT) to=SHORT;
  1626.             if(c==CONVUSHORT) to=UNSIGNED|SHORT;
  1627.             if(c==CONVINT) to=LONG;
  1628.             if(c==CONVUINT) to=UNSIGNED|LONG;
  1629.             if(c==CONVLONG) to=LONG;
  1630.             if(c==CONVULONG) to=UNSIGNED|LONG;
  1631.             if(c==CONVFLOAT) to=FLOAT;
  1632.             if(c==CONVDOUBLE) to=DOUBLE;
  1633.             if(c==CONVPOINTER) to=UNSIGNED|LONG;
  1634.             if(c==CONVVOID){ierror(0);continue;}
  1635.             if(t==FLOAT||t==DOUBLE||to==FLOAT||to==DOUBLE){
  1636.                 if(g_flags_val[1].l>=68000){
  1637.                     int zreg=0;
  1638.                     if((t==FLOAT||t==DOUBLE)&&(to==FLOAT||to==DOUBLE)){
  1639.                         if(isreg(q1)&&isreg(z)){
  1640.                             if(p->q1.reg!=p->z.reg)
  1641.                                 fprintf(f,"\tfmove.x\t%s,%s\n",regnames[p->q1.reg],regnames[p->z.reg]);
  1642.                             continue;
  1643.                         }
  1644.                     }
  1645.                     if(isreg(z)&&p->z.reg>=17)
  1646.                         zreg=p->z.reg;
  1647.                     if(isreg(q1)&&p->q1.reg>=17){
  1648.                         if(!zreg) zreg=p->q1.reg; else zreg=get_reg(f,2,p);}
  1649.                     if(!zreg) zreg=get_reg(f,2,p);
  1650.                     if((to&UNSIGNED)&&x_t[to&15]!='l'){
  1651.                         int dreg=get_reg(f,1,p);
  1652.                         fprintf(f,"\tmoveq\t#0,%s\n",regnames[dreg]);
  1653.                         move(f,&p->q1,0,0,dreg,to);
  1654.                         move(f,0,dreg,0,zreg,LONG);
  1655.                     }else{
  1656.                         if(!isreg(q1)||p->q1.reg!=zreg)
  1657.                             move(f,&p->q1,0,0,zreg,to);
  1658.                     }
  1659.                     if(t!=FLOAT&&t!=DOUBLE){
  1660.                     /*  nach integer, d.h. Kommastellen abschneiden */
  1661.                         if(g_flags_val[1].l==68040/*||g_flags_val[1].l==68060*/){
  1662.                         /*  bei 040 emuliert    */
  1663.                             int dreg1=get_reg(f,1,p),dreg2=get_reg(f,1,p);
  1664.                             fprintf(f,"\tfmove.l\tfpcr,%s\n",regnames[dreg2]);
  1665.                             fprintf(f,"\tmoveq\t#16,%s\n",regnames[dreg1]);
  1666.                             fprintf(f,"\tor.l\t%s,%s\n",regnames[dreg2],regnames[dreg1]);
  1667.                             fprintf(f,"\tand.w\t#-33,%s\n",regnames[dreg1]);
  1668.                             fprintf(f,"\tfmove.l\t%s,fpcr\n",regnames[dreg1]);
  1669.                             fprintf(f,"\tfmove.%c\t%s,",x_t[t&15],regnames[zreg]);
  1670.                             probj2(f,&p->z,t);fprintf(f,"\n");
  1671.                             fprintf(f,"\tfmove.l\t%s,fpcr\n",regnames[dreg2]);
  1672.                             continue;
  1673.                         }else{
  1674.                             if(!isreg(q1)||p->q1.reg!=zreg){
  1675.                                 fprintf(f,"\tfintrz.x\t%s\n",regnames[zreg]);
  1676.                             }else{
  1677.                                 int nreg=get_reg(f,2,p);
  1678.                                 fprintf(f,"\tfintrz.x\t%s,%s\n",regnames[zreg],regnames[nreg]);
  1679.                                 zreg=nreg;
  1680.                             }
  1681.                         }
  1682.                     }
  1683.                     if(to&UNSIGNED&&x_t[to&15]=='l'){
  1684.                         int nlabel;
  1685.                         fprintf(f,"\ttst.%c\t",x_t[to&15]);
  1686.                         probj2(f,&p->q1,to);fprintf(f,"\n");
  1687.                         nlabel=++label;
  1688.                         fprintf(f,"\tbge.s\tl%d\n",nlabel);
  1689.                         fprintf(f,"\tfadd.d\t#4294967296,%s\n",regnames[zreg]);
  1690.                         fprintf(f,"l%d:\n",nlabel);
  1691.                     }
  1692.                     if(!(p->z.reg)||p->z.reg!=zreg){
  1693.                         move(f,0,zreg,&p->z,0,t);
  1694.                     }
  1695.                 }else{
  1696.                     cc_set=0;
  1697.                     if(to==t){
  1698.                         assign(f,p,&p->q1,&p->z,ASSIGN,zl2l(p->q2.val.vlong),t);
  1699.                         continue;
  1700.                     }
  1701.                     if(to==FLOAT&&t==DOUBLE){
  1702.                         saveregs(f,p);
  1703.                         assign(f,p,&p->q1,0,PUSH,msizetab[FLOAT],FLOAT);
  1704.                         if(gas){
  1705.                             fprintf(f,"\t.global\t__ieees2d\n\tjbsr\t__ieees2d\n\taddq.w\t#4,a7\n");
  1706.                         }else{
  1707.                             fprintf(f,"\tpublic\t__ieees2d\n\tjsr\t__ieees2d\n\taddq.w\t#4,a7\n");
  1708.                         }
  1709.                         stackoffset+=4;
  1710.                         restoreregsa(f,p);
  1711.                         fprintf(f,"\tmovem.l\td0/d1,");
  1712.                         probj2(f,&p->z,t);fprintf(f,"\n");
  1713.                         restoreregsd(f,p);
  1714.                         continue;
  1715.                     }
  1716.                     if(to==DOUBLE&&t==FLOAT){
  1717.                         saveregs(f,p);
  1718.                         assign(f,p,&p->q1,0,PUSH,msizetab[DOUBLE],DOUBLE);
  1719.                         if(gas){
  1720.                             fprintf(f,"\t.global\t__ieeed2s\n\tjbsr\t__ieeed2s\n\taddq.w\t#8,a7\n");
  1721.                         }else{
  1722.                             fprintf(f,"\tpublic\t__ieeed2s\n\tjsr\t__ieeed2s\n\taddq.w\t#8,a7\n");
  1723.                         }
  1724.                         stackoffset+=8;
  1725.                         restoreregsa(f,p);
  1726.                         move(f,0,9,&p->z,0,t);
  1727.                         restoreregsd(f,p);
  1728.                         continue;
  1729.                     }
  1730.                     if(to==FLOAT||to==DOUBLE){
  1731.                         int uns;
  1732.                         saveregs(f,p);
  1733.                         if(t&UNSIGNED) uns='u'; else uns='s';
  1734.                         assign(f,p,&p->q1,0,PUSH,sizetab[to&15],to);
  1735.                         if(gas){
  1736.                             fprintf(f,"\t.global\t__ieeefix%c%c\n\tjbsr\t__ieeefix%c%c\n\taddq.w\t#%ld,a7\n",x_t[to&15],uns,x_t[to&15],uns,sizetab[to&15]);
  1737.                         }else{
  1738.                             fprintf(f,"\tpublic\t__ieeefix%c%c\n\tjsr\t__ieeefix%c%c\n\taddq.w\t#%ld,a7\n",x_t[to&15],uns,x_t[to&15],uns,sizetab[to&15]);
  1739.                         }
  1740.                         stackoffset+=sizetab[to&15];
  1741.                         restoreregsa(f,p);
  1742.                         move(f,0,9,&p->z,0,t);
  1743.                         restoreregsd(f,p);
  1744.                         continue;
  1745.                     }else{
  1746.                         int uns,xt=x_t[to&15];
  1747.                         saveregs(f,p);
  1748.                         if(to&UNSIGNED) uns='u'; else uns='s';
  1749.                         if(xt!='l') {fprintf(f,"\tsubq.w\t#4,a7\n");stackoffset-=4;}
  1750.                         fprintf(f,"\tmove.%c\t",xt);
  1751.                         probj2(f,&p->q1,to);
  1752.                         if(xt!='l') fprintf(f,",(a7)\n"); else {fprintf(f,",-(a7)\n");stackoffset-=4;}
  1753.                         if(gas){
  1754.                             fprintf(f,"\t.global\t__ieeeflt%c%c%c\n\tjbsr\t__ieeeflt%c%c%c\n\taddq.w\t#4,a7\n",uns,xt,x_t[t&15],uns,xt,x_t[t&15]);
  1755.                         }else{
  1756.                             fprintf(f,"\tpublic\t__ieeeflt%c%c%c\n\tjsr\t__ieeeflt%c%c%c\n\taddq.w\t#4,a7\n",uns,xt,x_t[t&15],uns,xt,x_t[t&15]);
  1757.                         }
  1758.                         stackoffset+=4;
  1759.                         restoreregsa(f,p);
  1760.                         if(t==DOUBLE){
  1761.                             fprintf(f,"\tmovem.l\td0/d1,");
  1762.                             probj2(f,&p->z,t);fprintf(f,"\n");
  1763.                         }else move(f,0,9,&p->z,0,t);
  1764.                         restoreregsd(f,p);
  1765.                         continue;
  1766.                     }
  1767.                 }
  1768.                 continue;
  1769.             }
  1770.             if((to&15)<(t&15)){
  1771.                 int zreg;
  1772.                 if(isreg(z)&&p->z.reg>=9&&p->z.reg<=16)
  1773.                     zreg=p->z.reg; else zreg=get_reg(f,1,p);
  1774.                 /*  aufpassen, falls unsigned und Quelle==Ziel  */
  1775.                 if((to&UNSIGNED)&&isreg(q1)&&zreg==p->q1.reg){
  1776.                     unsigned long l;
  1777.                     if((to&15)==CHAR) l=0xff; else l=0xffff;
  1778.                     fprintf(f,"\tand.%c\t#%lu,%s\n",x_t[t&15],l,regnames[zreg]);
  1779.                     continue;
  1780.                 }
  1781.                 if(to&UNSIGNED) fprintf(f,"\tmoveq\t#0,%s\n",regnames[zreg]);
  1782.                 move(f,&p->q1,0,0,zreg,to);
  1783.                 if(!(to&UNSIGNED)){
  1784.                     if((to&15)==CHAR&&(t&15)==SHORT) fprintf(f,"\text.w\t%s\n",regnames[zreg]);
  1785.                     if((to&15)==SHORT&&msizetab[t&15]==4) fprintf(f,"\text.l\t%s\n",regnames[zreg]);
  1786.                     if((to&15)==CHAR&&msizetab[t&15]==4){
  1787.                         if(g_flags_val[0].l>=68020)
  1788.                             fprintf(f,"\textb.l\t%s\n",regnames[zreg]);
  1789.                         else
  1790.                             fprintf(f,"\text.w\t%s\n\text.l\t%s\n",regnames[zreg],regnames[zreg]);
  1791.                     }
  1792.                 }
  1793.                 if(!isreg(z)||p->z.reg!=zreg){
  1794.                     move(f,0,zreg,&p->z,0,t);
  1795.                 }
  1796.             }else{
  1797.                 long diff;int m;
  1798.                 m=0;
  1799.                 if(p->q1.flags®){
  1800.                     p->q1.val.vlong=l2zl(0L);
  1801.                     p->q1.flags|=D16OFF;m=1;
  1802.                 }
  1803.                 diff=msizetab[to&15]-msizetab[t&15];
  1804.                 vlong=l2zl(diff);
  1805.                 p->q1.val.vlong=zladd(p->q1.val.vlong,vlong);
  1806.                 move(f,&p->q1,0,&p->z,0,t);
  1807.                 vlong=l2zl(diff);
  1808.                 p->q1.val.vlong=zlsub(p->q1.val.vlong,vlong);
  1809.                 if(m) p->q1.flags&=~D16OFF;
  1810.             }
  1811.             continue;
  1812.         }
  1813.         if((t==FLOAT||t==DOUBLE)&&g_flags_val[1].l>=68000) *fp='f'; else *fp=0;
  1814.         if(c==MINUS||c==KOMPLEMENT){
  1815.             int zreg;
  1816.             if(t==FLOAT||t==DOUBLE){
  1817.                 if(g_flags_val[1].l>=68000){
  1818.                     if(isreg(z)) zreg=p->z.reg; else zreg=get_reg(f,2,p);
  1819.                     fprintf(f,"\tfneg.");
  1820.                     if(isreg(q1)) fprintf(f,"x\t%s",regnames[p->q1.reg]);
  1821.                         else    {fprintf(f,"%c\t",x_t[t&15]);probj2(f,&p->q1,t);}
  1822.                     fprintf(f,",%s\n",regnames[zreg]);
  1823.                     if(!isreg(z)||p->z.reg!=zreg){
  1824.                         move(f,0,zreg,&p->z,0,t);
  1825.                     }
  1826.                     continue;
  1827.                 }else{
  1828.                     saveregs(f,p);
  1829.                     assign(f,p,&p->q1,0,PUSH,msizetab[t&15],t);
  1830.                     if(gas){
  1831.                         fprintf(f,"\t.global\t__ieeeneg%c\n\tjbsr\t__ieeeneg%c\n\taddq.w\t#%ld,a7\n",x_t[t&15],x_t[t&15],msizetab[t&15]);
  1832.                     }else{
  1833.                         fprintf(f,"\tpublic\t__ieeeneg%c\n\tjsr\t__ieeeneg%c\n\taddq.w\t#%ld,a7\n",x_t[t&15],x_t[t&15],msizetab[t&15]);
  1834.                     }
  1835.                     stackoffset+=msizetab[t&15];
  1836.                     restoreregsa(f,p);
  1837.                     if(t==DOUBLE){
  1838.                         fprintf(f,"\tmovem.l\td0/d1,");
  1839.                         probj2(f,&p->z,t);fprintf(f,"\n");
  1840.                     }else move(f,0,9,&p->z,0,t);
  1841.                     restoreregsd(f,p);
  1842.                     continue;
  1843.                 }
  1844.             }
  1845.             if(compare_objects(&p->q1,&p->z)){
  1846.                 fprintf(f,"\t%s.%c\t",ename[c],x_t[t&15]);
  1847.                 probj2(f,&p->q1,t);fprintf(f,"\n");
  1848.                 continue;
  1849.             }
  1850.             if(isreg(z)&&p->z.reg>=9/*&&p->z.reg<=16*/)
  1851.                 zreg=p->z.reg; else zreg=get_reg(f,1,p);
  1852.             if(!isreg(q1)||p->q1.reg!=zreg){
  1853.                 move(f,&p->q1,0,0,zreg,t);
  1854.             }
  1855.             fprintf(f,"\t%s.%c\t%s\n",ename[c],x_t[t&15],regnames[zreg]);
  1856.             if(!isreg(z)||p->z.reg!=zreg){
  1857.                 move(f,0,zreg,&p->z,0,t);
  1858.             }
  1859.             continue;
  1860.         }
  1861.         if(c==SETRETURN){
  1862.         /*  Returnwert setzen - q2.val.vlong==size, z.reg==Returnregister */
  1863.             if((t&15)==DOUBLE&&p->z.reg==9){
  1864.                 if(p->q1.flags&KONST){
  1865.                     unsigned char *ip=(unsigned char *)&p->q1.val.vdouble;
  1866.                     char *s;
  1867.                     if(gas) s="0x"; else s="$";
  1868.                     fprintf(f,"\tmove.l\t#%s%02x%02x%02x%02x,d0\n",s,ip[0],ip[1],ip[2],ip[3]);
  1869.                     fprintf(f,"\tmove.l\t#%s%02x%02x%02x%02x,d1\n",s,ip[4],ip[5],ip[6],ip[7]);
  1870.                     continue;
  1871.                 }
  1872.                 if(isreg(q1)){
  1873.                     fprintf(f,"\tfmove.d\t%s,-(a7)\n\tmovem.l\t(a7)+",regnames[p->q1.reg]);
  1874.                 }else{
  1875.                     fprintf(f,"\tmovem.l\t");probj2(f,&p->q1,t);
  1876.                 }
  1877.                 fprintf(f,",d0/d1\n");
  1878.                 continue;
  1879.             }
  1880.             if(((t&15)==STRUCT||(t&15)==UNION)&&p->z.reg==9){
  1881.                 long l=zl2l(p->q2.val.vlong);
  1882.                 fprintf(f,"\tmovem.l\t");probj2(f,&p->q1,t);
  1883.                 fprintf(f,",d0");
  1884.                 if(l>=8) fprintf(f,"/d1");
  1885.                 if(l>=12) fprintf(f,"/a0");
  1886.                 if(l>=16) fprintf(f,"/a1");
  1887.                 fprintf(f,"\n");
  1888.                 continue;
  1889.             }
  1890.         /*  Wenn Returnwert ueber Zeiger gesetzt wird, nichts noetig    */
  1891.             if(p->z.reg) move(f,&p->q1,0,0,p->z.reg,p->typf);
  1892.             continue;
  1893.         }
  1894.         if(c==GETRETURN){
  1895.         /*  Returnwert holen - q2.val.vlong==size, q1.reg==Returnregister     */
  1896.             if((t&15)==DOUBLE&&p->q1.reg==9){
  1897.                 fprintf(f,"\tmovem.l\td0/d1");
  1898.                 if(isreg(z)){
  1899.                     fprintf(f,",-(a7)\n\tfmove.d\t(a7)+,%s\n",regnames[p->z.reg]);
  1900.                 }else{
  1901.                     fprintf(f,",");probj2(f,&p->z,t);fprintf(f,"\n");
  1902.                 }
  1903.                 continue;
  1904.             }
  1905.             if(((t&15)==STRUCT||(t&15)==UNION)&&p->q1.reg==9){
  1906.                 long l=zl2l(p->q2.val.vlong);
  1907.                 fprintf(f,"\tmovem.l\t");
  1908.                 fprintf(f,"d0");
  1909.                 if(l>=8) fprintf(f,"/d1");
  1910.                 if(l>=12) fprintf(f,"/a0");
  1911.                 if(l>=16) fprintf(f,"/a1");
  1912.                 fprintf(f,",");probj2(f,&p->z,t);fprintf(f,"\n");
  1913.                 continue;
  1914.             }
  1915.  
  1916.         /*  Wenn Returnwert ueber Zeiger gesetzt wird, nichts noetig    */
  1917.             cc_set=0;
  1918.             if(p->q1.reg){
  1919.                 move(f,0,p->q1.reg,&p->z,0,p->typf);
  1920.                 if(!(p->z.flags®)||(p->z.reg!=p->q1.reg&&p->z.reg>=9)){ cc_set=&p->z;cc_typ=p->typf;}
  1921.             }
  1922.             continue;
  1923.         }
  1924.         if(c==CALL){
  1925.             if(gas){
  1926.                 fprintf(f,"\tjbsr\t");
  1927.             }else{
  1928.                 fprintf(f,"\tjsr\t");
  1929.             }
  1930.             /*  Wenn geta4() aufgerufen wurde, merken.  */
  1931.             if((p->q1.flags&(VAR|DREFOBJ))==VAR&&!strcmp(p->q1.v->identifier,"geta4")&&p->q1.v->storage_class==EXTERN)
  1932.                 geta4=1;
  1933.             if((p->q1.flags&(DREFOBJ|REG))==DREFOBJ) ierror(0);
  1934.             probj2(f,&p->q1,t);
  1935.             fprintf(f,"\n");
  1936.             if(dbout) act_line=0;
  1937.             if(zl2l(p->q2.val.vlong)){
  1938.                 notpopped+=zl2l(p->q2.val.vlong);
  1939.                 dontpop-=zl2l(p->q2.val.vlong);
  1940.                 if(!(g_flags[10]&USEDFLAG)&&!(pushedreg&30)&&stackoffset==-notpopped){
  1941.                 /*  Entfernen der Parameter verzoegern  */
  1942.                 }else{
  1943.                     if(dbout&&!gas){ act_line=p->line; fprintf(f,"\tdebug\t%d\n",act_line);}
  1944.                     fprintf(f,"\tadd%s.%s\t#%ld,a7\n",quick[zl2l(p->q2.val.vlong)<=8],strshort[zl2l(p->q2.val.vlong)<32768],zl2l(p->q2.val.vlong));
  1945.                     stackoffset+=zl2l(p->q2.val.vlong);
  1946.                     notpopped-=zl2l(p->q2.val.vlong);
  1947.                 }
  1948.             }
  1949.             continue;
  1950.         }
  1951.         if(c==TEST){
  1952.             /*  ConditionCodes schon gesetzt?   */
  1953.             cc_set=&p->q1;cc_typ=t;
  1954.             comptyp=t;
  1955.             if(cc_set_tst&&t==cc_typ_tst){
  1956.                 struct IC *branch;
  1957.                 if(t&UNSIGNED){
  1958.                     branch=p->next;
  1959.                     while(branch&&(branch->code<BEQ||branch->code>BGT))
  1960.                         branch=branch->next;
  1961.                     if(!branch) ierror(0);
  1962.                     if(branch->code==BLE) branch->code=BEQ;
  1963.                     if(branch->code==BGT) branch->code=BNE;
  1964.                     if(branch->code==BGE) {branch->code=BRA;continue;}
  1965.                     if(branch->code==BLT) {branch->code=NOP;continue;}
  1966.                 }
  1967.                 if(compare_objects(&p->q1,cc_set_tst)&&p->q1.am==cc_set_tst->am&&zleqto(p->q1.val.vlong,cc_set_tst->val.vlong)){
  1968.                     if(DEBUG&512){fprintf(f,"; tst eliminated: cc=");probj2(f,cc_set_tst,t);
  1969.                                   fprintf(f,", q1=");probj2(f,&p->q1,t);fprintf(f,"\n");}
  1970.                     continue;
  1971.                 }
  1972.             }
  1973.             if(g_flags_val[0].l<68020&&isreg(q1)&&p->q1.reg>=1&&p->q1.reg<=8){
  1974.             /*  tst ax gibt es nicht bei <68000 :-( */
  1975.                 if(regavailable(1)){
  1976.                     fprintf(f,"\tmove.%c\t%s,%s\n",x_t[t&15],regnames[p->q1.reg],regnames[get_reg(f,1,p)]);
  1977.                 }else{
  1978.                     fprintf(f,"\tcmp.w\t#0,%s\n",regnames[p->q1.reg]);
  1979.                 }
  1980.                 continue;
  1981.             }
  1982.             if((t==DOUBLE||t==FLOAT)&&g_flags_val[1].l<68000){
  1983.             /*  nicht sehr schoen   */
  1984.                 int result=get_reg(f,1,p);
  1985.                 saveregs(f,p);
  1986.                 assign(f,p,&p->q1,0,PUSH,msizetab[t&15],t);
  1987.                 if(gas){
  1988.                     fprintf(f,"\t.global\t__ieeetst%c\n\tjbsr\t__ieeetst%c\n\taddq.w\t#%ld,a7\n",x_t[t&15],x_t[t&15],msizetab[t&15]);
  1989.                 }else{
  1990.                     fprintf(f,"\tpublic\t__ieeetst%c\n\tjsr\t__ieeetst%c\n\taddq.w\t#%ld,a7\n",x_t[t&15],x_t[t&15],msizetab[t&15]);
  1991.                 }
  1992.                 stackoffset+=msizetab[t&15];
  1993.                 restoreregsa(f,p);
  1994.                 if(result!=9) fprintf(f,"\tmove.l\td0,%s\n",regnames[result]);
  1995.                 fprintf(f,"\ttst.l\t%s\n",regnames[result]);
  1996.                 restoreregsd(f,p);
  1997.                 continue;
  1998.             }
  1999.             if(isreg(q1)&&p->q1.reg>=17){fprintf(f,"\tftst.x\t%s\n",regnames[p->q1.reg]);continue;}
  2000.             fprintf(f,"\t%stst.%c\t",fp,x_t[t&15]);probj2(f,&p->q1,t);
  2001.             fprintf(f,"\n");
  2002.             continue;
  2003.         }
  2004.         if(c==ASSIGN||c==PUSH){
  2005.             if(c==ASSIGN&&compare_objects(&p->q1,&p->z)) cc_set=0;
  2006.             if(c==PUSH) dontpop+=zl2l(p->q2.val.vlong);
  2007.             assign(f,p,&p->q1,&p->z,c,zl2l(p->q2.val.vlong),t);
  2008.             continue;
  2009.         }
  2010.         if(c==ADDRESS){
  2011.             int zreg;
  2012.             if(isreg(z)&&p->z.reg>=1&&p->z.reg<=8)
  2013.                 zreg=p->z.reg; else zreg=get_reg(f,0,p);
  2014.             fprintf(f,"\tlea\t");probj2(f,&p->q1,t);
  2015.             fprintf(f,",%s\n",regnames[zreg]);
  2016.             if(!isreg(z)||p->z.reg!=zreg){
  2017.                 move(f,0,zreg,&p->z,0,POINTER);
  2018.             }
  2019.             continue;
  2020.         }
  2021.         if(c==COMPARE){
  2022.             int zreg;
  2023.             comptyp=t;
  2024.             if((p->q1.flags&KONST)||isreg(q2)){
  2025.             /*  evtl. Argumente von cmp und nachfolgendes bcc umdrehen  */
  2026.                 struct IC *n;struct obj m;
  2027.                 n=p->next;
  2028.                 while(n){
  2029.                     if(n->code>=BEQ&&n->code<BRA){
  2030.                         if(!p->z.flags){
  2031.                             if(DEBUG&1) printf("arguments of cmp exchanged\n");
  2032.                             m=p->q1;p->q1=p->q2;p->q2=m;
  2033.                             p->z.flags=1;
  2034.                         }
  2035.                         /*  nachfolgenden Branch umdrehen   */
  2036.                         switch(n->code){
  2037.                             case BGT: n->code=BLT;break;
  2038.                             case BLT: n->code=BGT;break;
  2039.                             case BGE: n->code=BLE;break;
  2040.                             case BLE: n->code=BGE;break;
  2041.                         }
  2042.                         break;
  2043.                     }
  2044.                     if(n->code==FREEREG) n=n->next; else break; /*  compare ohne branch => leerer Block o.ae.   */
  2045.                 }
  2046.             }
  2047.             if(t==FLOAT||t==DOUBLE){
  2048.                 if(g_flags_val[1].l>=68000){
  2049.                     if(isreg(q1)&&p->q1.reg>=17){
  2050.                         zreg=p->q1.reg;
  2051.                     }else{
  2052.                         zreg=get_reg(f,2,p);
  2053.                         move(f,&p->q1,0,0,zreg,t);
  2054.                     }
  2055.                     if(isreg(q2)){fprintf(f,"\tfcmp.x\t%s,%s\n",regnames[p->q2.reg],regnames[zreg]);continue;}
  2056.                     fprintf(f,"\tfcmp.%c\t",x_t[t&15]);probj2(f,&p->q2,t);
  2057.                     fprintf(f,",%s\n",regnames[zreg]);
  2058.                     continue;
  2059.                 }else{
  2060.                 /*  nicht sehr schoen   */
  2061.                     int result=get_reg(f,1,p);
  2062.                     saveregs(f,p);
  2063.                     assign(f,p,&p->q2,0,PUSH,msizetab[t&15],t);
  2064.                     assign(f,p,&p->q1,0,PUSH,msizetab[t&15],t);
  2065.                     if(gas){
  2066.                         fprintf(f,"\t.global\t__ieeecmp%c\n\tjbsr\t__ieeecmp%c\n\tadd.w\t#%ld,a7\n",x_t[t&15],x_t[t&15],2*msizetab[t&15]);
  2067.                     }else{
  2068.                         fprintf(f,"\tpublic\t__ieeecmp%c\n\tjsr\t__ieeecmp%c\n\tadd.w\t#%ld,a7\n",x_t[t&15],x_t[t&15],2*msizetab[t&15]);
  2069.                     }
  2070.                     stackoffset+=2*msizetab[t&15];
  2071.                     restoreregsa(f,p);
  2072.                     if(result!=9) fprintf(f,"\tmove.l\td0,%s\n",regnames[result]);
  2073.                     fprintf(f,"\ttst.l\t%s\n",regnames[result]);
  2074.                     restoreregsd(f,p);
  2075.                     continue;
  2076.                 }
  2077.             }
  2078.             if(p->q2.flags&KONST){
  2079.                 fprintf(f,"\tcmp.%c\t",x_t[t&15]);probj2(f,&p->q2,t);
  2080.                 fprintf(f,",");probj2(f,&p->q1,t);fprintf(f,"\n");
  2081.                 continue;
  2082.             }
  2083.             if(isreg(q1)){
  2084.                 zreg=p->q1.reg;
  2085.             }else{
  2086.                 zreg=get_reg(f,1,p);    /* hier evtl. auch Adressregister nehmen */
  2087.                 move(f,&p->q1,0,0,zreg,t);
  2088.             }
  2089.             fprintf(f,"\tcmp.%c\t",x_t[t&15]);probj2(f,&p->q2,t);
  2090.             fprintf(f,",%s\n",regnames[zreg]);
  2091.             continue;
  2092.         }
  2093.         if(c==ADDI2P||c==SUBIFP){
  2094.             int zreg,r;
  2095.             if(isreg(q1)&&p->q1.reg<=8&&isreg(z)&&p->z.reg<=8&&p->q1.reg!=p->z.reg){
  2096.             /*  q1 und z Adressregister => lea nehmen   */
  2097.                 if(p->q2.flags&KONST){
  2098.                     eval_const(&p->q2.val,t);
  2099.                     if(c==SUBIFP) vlong=zlsub(l2zl(0L),vlong);
  2100.                     if(g_flags_val[0].l>=68020||(zlleq(vlong,l2zl(32767))&&zlleq(l2zl(-32768),vlong))){
  2101.                         fprintf(f,"\tlea\t(%ld,%s),%s\n",zl2l(vlong),regnames[p->q1.reg],regnames[p->z.reg]);
  2102.                         continue;
  2103.                     }
  2104.                 }else if(c==ADDI2P&&isreg(q2)){
  2105.                     fprintf(f,"\tlea\t(%s,%s.%c),%s\n",regnames[p->q1.reg],regnames[p->q2.reg],x_t[t&15],regnames[p->z.reg]);
  2106.                     continue;
  2107.                 }
  2108.             }
  2109.             if(compare_objects(&p->q1,&p->z)){
  2110.                 if(p->q2.flags&KONST){
  2111.                     if(c==ADDI2P)
  2112.                         fprintf(f,"\tadd%s.l\t",quick[isquickkonst2(&p->q2.val,t)]);
  2113.                     else
  2114.                         fprintf(f,"\tsub%s.l\t",quick[isquickkonst2(&p->q2.val,t)]);
  2115.                     probj2(f,&p->q2,t);fprintf(f,",");
  2116.                     probj2(f,&p->z,POINTER);fprintf(f,"\n");
  2117.                     continue;
  2118.                 }
  2119.                 if(isreg(q1)&&(x_t[t&15]=='l'||p->q1.reg<=8)){
  2120.                     if(c==ADDI2P)
  2121.                         fprintf(f,"\tadd.%c\t",x_t[t&15]);
  2122.                     else
  2123.                         fprintf(f,"\tsub.%c\t",x_t[t&15]);
  2124.                     probj2(f,&p->q2,t);fprintf(f,",%s\n",regnames[p->z.reg]);
  2125.                     continue;
  2126.                 }
  2127.                 if(isreg(q2)&&p->q2.reg>=1){
  2128.                     r=p->q2.reg;
  2129.                 }else{
  2130.                     r=get_reg(f,1,p);
  2131.                     move(f,&p->q2,0,0,r,t);
  2132.                 }
  2133.                 if(x_t[t&15]!='l'&&(!isreg(z)||p->z.reg<1||p->z.reg>8)){
  2134.                 /*  wenn Ziel kein Adressregister, muss short erst auf long */
  2135.                 /*  char darf hier nicht auftreteten und long passt schon   */
  2136.                     if(t&UNSIGNED) fprintf(f,"\tswap\t%s\n\tclr.w\t%s\n\tswap\t%s\n",regnames[r],regnames[r],regnames[r]);
  2137.                      else          fprintf(f,"\text.l\t%s\n",regnames[r]);
  2138.                     t=POINTER;
  2139.                 }
  2140. /*                if(c==ADDI2P)
  2141.                     fprintf(f,"\tadd.%c\t%s,",x_t[t&15],regnames[r]);
  2142.                 else
  2143.                     fprintf(f,"\tsub.%c\t%s,",x_t[t&15],regnames[r]);
  2144.                 probj2(f,&p->z,t);fprintf(f,"\n");*/
  2145.                 if(c==ADDI2P) add(f,0,r,&p->z,0,t);
  2146.                  else         sub(f,0,r,&p->z,0,t);
  2147.                 continue;
  2148.             }
  2149.             if(isreg(z)&&p->z.reg>=1&&p->z.reg<=16)
  2150.                 zreg=p->z.reg; else zreg=get_reg(f,0,p);
  2151.             /*  Spezialfall, falls Ziel Datenregister und short */
  2152.             /*  nicht schoen, aber auf die Schnelle...          */
  2153.             if(x_t[t&15]!='l'&&zreg>8){
  2154.                 move(f,&p->q2,0,0,zreg,t);
  2155.                 if(t&UNSIGNED) fprintf(f,"\tswap\t%s\n\tclr.w\t%s\n\tswap\t%s\n",regnames[zreg],regnames[zreg],regnames[zreg]);
  2156.                  else          fprintf(f,"\text.l\t%s\n",regnames[zreg]);
  2157.                 if(c==SUBIFP) fprintf(f,"\tneg.l\t%s\n",regnames[zreg]);
  2158.                 add(f,&p->q1,0,0,zreg,POINTER);
  2159.                 if(!isreg(z)||p->z.reg!=zreg)
  2160.                     move(f,0,zreg,&p->z,0,POINTER);
  2161.                 continue;
  2162.             }
  2163.             if(!isreg(q1)||p->q1.reg!=zreg){
  2164.                 move(f,&p->q1,0,0,zreg,POINTER);
  2165.             }
  2166.             if(c==ADDI2P) add(f,&p->q2,0,0,zreg,t);
  2167.              else         sub(f,&p->q2,0,0,zreg,t);
  2168.             if(!isreg(z)||p->z.reg!=zreg){
  2169.                 move(f,0,zreg,&p->z,0,POINTER);
  2170.             }
  2171.             continue;
  2172.         }
  2173.         if((c>=OR&&c<=AND)||(c>=LSHIFT&&c<=MOD)){
  2174.             int zreg,q1reg,q2reg;
  2175.             if((p->q2.flags&KONST)&&
  2176.                (!(p->q1.flags®)||!(p->z.flags®)||p->q1.reg!=p->z.reg)&&
  2177.                (!(p->q1.flags&VAR)||!(p->z.flags&VAR)||p->q1.v!=p->z.v)&&
  2178.                ((c>=OR&&c<=AND)||c==ADD||c==MULT)){
  2179.                 struct obj o;
  2180.                 if(c==MULT){
  2181.                     eval_const(&p->q2.val,t);
  2182.                     if(zlleq(l2zl(0L),vlong)&&zulleq(ul2zul(0UL),vulong)&&!pof2(vulong)){
  2183.                         o=p->q1;p->q1=p->q2;p->q2=o;
  2184.                     }
  2185.                 }else{
  2186.                     o=p->q1;p->q1=p->q2;p->q2=o;
  2187.                 }
  2188.             }
  2189.             if(t==FLOAT||t==DOUBLE){
  2190.                 if(g_flags_val[1].l>=68000){
  2191.                     if(isreg(z)&&p->z.reg>=17) zreg=p->z.reg;
  2192.                         else zreg=get_reg(f,2,p);
  2193.                     if(!isreg(q1)||p->q1.reg!=p->z.reg)
  2194.                         move(f,&p->q1,0,0,zreg,t);
  2195.                     fprintf(f,"\tf%s.",ename[c]);
  2196.                     if(isreg(q2)) fprintf(f,"x\t");
  2197.                         else      fprintf(f,"%c\t",x_t[t&15]);
  2198.                     probj2(f,&p->q2,t);
  2199.                     fprintf(f,",%s\n",regnames[zreg]);
  2200.                     if(!isreg(z)||p->z.reg!=zreg){
  2201.                         move(f,0,zreg,&p->z,0,t);
  2202.                     }
  2203.                     continue;
  2204.                 }else{
  2205.                     saveregs(f,p);
  2206.                     assign(f,p,&p->q2,0,PUSH,msizetab[t&15],t);
  2207.                     assign(f,p,&p->q1,0,PUSH,msizetab[t&15],t);
  2208.                     if(gas){
  2209.                         fprintf(f,"\t.global\t__ieee%s%c\n\tjbsr\t__ieee%s%c\n\tadd.w\t#%ld,a7\n",ename[c],x_t[t&15],ename[c],x_t[t&15],2*msizetab[t&15]);
  2210.                     }else{
  2211.                         fprintf(f,"\tpublic\t__ieee%s%c\n\tjsr\t__ieee%s%c\n\tadd.w\t#%ld,a7\n",ename[c],x_t[t&15],ename[c],x_t[t&15],2*msizetab[t&15]);
  2212.                     }
  2213.                     stackoffset+=2*msizetab[t&15];
  2214.                     restoreregsa(f,p);
  2215.                     if(t==DOUBLE){
  2216.                         fprintf(f,"\tmovem.l\td0/d1,");
  2217.                         probj2(f,&p->z,t);fprintf(f,"\n");
  2218.                     }else move(f,0,9,&p->z,0,t);
  2219.                     restoreregsd(f,p);
  2220.                     continue;
  2221.                 }
  2222.             }
  2223.             if((c==MULT||c==DIV||(c==MOD&&(p->typf&UNSIGNED)))&&(p->q2.flags&KONST)){
  2224.             /*  ersetzt mul etc. mit Zweierpotenzen     */
  2225.             /*  hier evtl. noch Fehler                  */
  2226.                 long ln;
  2227.                 eval_const(&p->q2.val,t);
  2228.                 if(zlleq(l2zl(0L),vlong)&&zulleq(ul2zul(0UL),vulong)){
  2229.                     if(ln=pof2(vulong)){
  2230.                         if(c==MOD){
  2231.                             vlong=zlsub(vlong,l2zl(1L));
  2232.                             p->code=AND;
  2233.                         }else{
  2234.                             vlong=l2zl(ln-1);
  2235.                             if(c==DIV) p->code=RSHIFT; else p->code=LSHIFT;
  2236.                         }
  2237.                         c=p->code;
  2238.                         if((t&31)==CHAR) p->q2.val.vchar=zl2zc(vlong);
  2239.                         if((t&31)==SHORT) p->q2.val.vshort=zl2zs(vlong);
  2240.                         if((t&31)==INT) p->q2.val.vint=zl2zi(vlong);
  2241.                         if((t&31)==LONG) p->q2.val.vlong=vlong;
  2242.                         vulong=zl2zul(vlong);
  2243.                         if((t&31)==(UNSIGNED|CHAR)) p->q2.val.vuchar=zul2zuc(vulong);
  2244.                         if((t&31)==(UNSIGNED|SHORT)) p->q2.val.vushort=zul2zus(vulong);
  2245.                         if((t&31)==(UNSIGNED|INT))  p->q2.val.vuint=zul2zui(vulong);
  2246.                         if((t&31)==(UNSIGNED|LONG)) p->q2.val.vulong=vulong;
  2247.                     }
  2248.                 }
  2249.             }
  2250.             if(c==DIV||c==MOD){
  2251.                 if(x_t[t&15]=='l'&&g_flags_val[0].l<68020){
  2252.                 /*  das hier ist auch nicht allzu schoen  */
  2253.                     char *fname;
  2254.                     cc_set=0;   /*  Library-Funktionen setzen cc nicht immer */
  2255.                     saveregs(f,p);
  2256.                     fprintf(f,"\tmove.l\t"); probj2(f,&p->q2,t);
  2257.                     fprintf(f,",-(a7)\n");
  2258.                     stackoffset-=4;
  2259.                     fprintf(f,"\tmove.l\t"); probj2(f,&p->q1,t);
  2260.                     fprintf(f,",-(a7)\n");
  2261.                     stackoffset-=4;
  2262.                     if(c==DIV){
  2263.                         if(t&UNSIGNED) fname="divu"; else fname="divs";
  2264.                     }else{
  2265.                         if(t&UNSIGNED) fname="modu"; else fname="mods";
  2266.                     }
  2267.                     if(gas){
  2268.                         fprintf(f,"\t.global\t__l%s\n\tjbsr\t__l%s\n",fname,fname);
  2269.                     }else{
  2270.                         fprintf(f,"\tpublic\t__l%s\n\tjsr\t__l%s\n",fname,fname);
  2271.                     }
  2272.                     fprintf(f,"\taddq.w\t#8,a7\n");
  2273.                     stackoffset+=8;
  2274.                     restoreregsa(f,p);
  2275.                     move(f,0,9,&p->z,0,t);
  2276.                     restoreregsd(f,p);
  2277.                     continue;
  2278.                 }
  2279.  
  2280.             }
  2281.             /*  hier die zweite Alternative mit isreg() schreiben?  */
  2282.             if(compare_objects(&p->q2,&p->z)){
  2283.                 struct obj m;
  2284.                 if((c>=OR&&c<=AND)||c==ADD||c==SUB){
  2285.                     if(c!=SUB){
  2286.                         m=p->q1;p->q1=p->q2;p->q2=m;
  2287.                     }else{
  2288.                         if(isreg(q2)&&p->q2.reg>=9&&p->q2.reg<=16){
  2289.                             m=p->q1;p->q1=p->q2;p->q2=m;
  2290.                             c=ADD;
  2291.                             fprintf(f,"\tneg.%c\t",x_t[t&15]);
  2292.                             probj2(f,&p->q1,t);fprintf(f,"\n");
  2293.                         }
  2294.                     }
  2295.                 }
  2296.             }
  2297.             if(compare_objects(&p->q1,&p->z)){
  2298.                 if((c>=OR&&c<=AND)||c==ADD||c==SUB){
  2299.                     int r;
  2300.                     if(p->q2.flags&KONST){
  2301.                         if(c==ADD) {add(f,&p->q2,0,&p->z,0,t);continue;}
  2302.                         if(c==SUB) {sub(f,&p->q2,0,&p->z,0,t);continue;}
  2303.                         fprintf(f,"\t%s.%c\t",ename[c],x_t[t&15]);
  2304.                         probj2(f,&p->q2,t);fprintf(f,",");
  2305.                         probj2(f,&p->z,t);fprintf(f,"\n");
  2306.                         continue;
  2307.                     }
  2308.                     if(!isreg(z)){
  2309.                         if(isreg(q2)&&p->q2.reg>=9&&p->q2.reg<=16)
  2310.                             r=p->q2.reg; else r=get_reg(f,1,p);
  2311.                         if(!isreg(q2)||p->q2.reg!=r){
  2312.                             move(f,&p->q2,0,0,r,t);
  2313.                         }
  2314.                         fprintf(f,"\t%s.%c\t%s,",ename[c],x_t[t&15],regnames[r]);
  2315.                         probj2(f,&p->z,t);fprintf(f,"\n");
  2316.                         continue;
  2317.                     }
  2318.                 }
  2319.             }
  2320.             /*  bei xor oder asl (ausser 0<=const<=8) muss q2 in Register   */
  2321.             if(isreg(q2)&&p->q2.reg>=9&&p->q2.reg<=16){
  2322.                 q2reg=p->q2.reg;
  2323.             }else{
  2324.                 if(c==LSHIFT||c==RSHIFT||c==XOR){
  2325.                     eval_const(&p->q2.val,t);
  2326.                     if(c==XOR||!(p->q2.flags&KONST)||!isquickkonst2(&p->q2.val,t)){
  2327.                         q2reg=get_reg(f,1,p);
  2328.                         move(f,&p->q2,0,0,q2reg,t);
  2329.                     }else q2reg=0;
  2330.                 }else{
  2331.                     q2reg=0;
  2332.                 }
  2333.             }
  2334.             if(c==MOD){
  2335.                 int modreg;
  2336.                 modreg=get_reg(f,1,p);
  2337.                 if(isreg(z)&&p->z.reg>=9&&p->z.reg<=16&&p->z.reg!=q2reg)
  2338.                     zreg=p->z.reg; else zreg=get_reg(f,1,p);
  2339.                 move(f,&p->q1,0,0,modreg,t);
  2340.                 if(0 /*g_flags_val[0].l==68060*/){
  2341.                 /*  div?l.l wird da emuliert?   */
  2342.                     fprintf(f,"\tsmi\t%s\n\textb.l\t%s\n",regnames[zreg],regnames[zreg]);
  2343.                     if(t&UNSIGNED) fprintf(f,"\tdivu.%c\t",x_t[t&15]); else fprintf(f,"\tdivs.%c\t",x_t[t&15]);
  2344.                 }else{
  2345.                     if(t&UNSIGNED) fprintf(f,"\tdivul.%c\t",x_t[t&15]); else fprintf(f,"\tdivsl.%c\t",x_t[t&15]);
  2346.                 }
  2347.                 probj2(f,&p->q2,t);
  2348.                 fprintf(f,",%s:%s\n",regnames[zreg],regnames[modreg]);
  2349.                 move(f,0,zreg,&p->z,0,t);
  2350.                 cc_set=0;
  2351.                 continue;
  2352.             }
  2353.             if(isreg(z)&&p->z.reg>=9&&p->z.reg<=16&&p->z.reg!=q2reg)
  2354.                 zreg=p->z.reg; else zreg=get_reg(f,1,p);
  2355.             if(isreg(q1)&&p->q1.reg>=9&&p->q1.reg<=16)
  2356.                 q1reg=p->q1.reg; else q1reg=0;
  2357.             if(q1reg!=zreg){
  2358.                 move(f,&p->q1,0,0,zreg,t);
  2359.             }
  2360.             if(c!=MULT&&c!=DIV&&c!=MOD&&c!=ADD&&c!=SUB){
  2361.                 if(c==RSHIFT&&!(t&UNSIGNED)) fprintf(f,"\tasr.%c\t",x_t[t&15]);
  2362.                  else fprintf(f,"\t%s.%c\t",ename[c],x_t[t&15]);
  2363.                 if(q2reg) fprintf(f,"%s",regnames[q2reg]); else probj2(f,&p->q2,t);
  2364.                 fprintf(f,",%s\n",regnames[zreg]);
  2365.             }else{
  2366.                 if(c==ADD) add(f,&p->q2,q2reg,0,zreg,t);
  2367.                 if(c==SUB) sub(f,&p->q2,q2reg,0,zreg,t);
  2368.                 if(c==MULT||c==DIV||c==MOD) mult(f,&p->q2,q2reg,0,zreg,t,c,p);
  2369.             }
  2370.             if((!isreg(z)||p->z.reg!=zreg)){
  2371.                 move(f,0,zreg,&p->z,0,t);
  2372.             }
  2373.             continue;
  2374.         }
  2375.         ierror(0);
  2376.     }
  2377.     if(notpopped){
  2378.         fprintf(f,"\tadd%s.%s\t#%ld,a7\n",quick[notpopped<=8],strshort[notpopped<32768],notpopped);
  2379.         stackoffset+=notpopped;notpopped=0;
  2380.     }
  2381.     function_bottom(f,v,zl2l(offset));
  2382.     if(pushflag){   /*  Speicher fuer pushlabel generieren - leider im cseg */
  2383.         if(gas){
  2384.             fprintf(f,"\t.lcomm\tl%d,4\n",pushlabel);
  2385.         }else{
  2386.             fprintf(f,"\tcnop\t0,4\nl%d\n\tds.b\t4\n",pushlabel);
  2387.         }
  2388.         pushflag=0;
  2389.     }
  2390. }
  2391.  
  2392. int shortcut(int code,int typ)
  2393. {
  2394.     if(code==COMPARE) return(1);
  2395.     return(0);
  2396. }
  2397.  
  2398. void cleanup_cg(FILE *f)
  2399. {
  2400.     return;
  2401. }
  2402.  
  2403.